c 调用objectivec-c怎么调用类接口

DevStore用户登录
还没有DevStore帐号?
快捷登录:
DevStore贯穿项目生命周期,解决你的所有问题
简述如何从Objective-C到Swift过渡
16:35 |DevStore编辑 糖果果
本篇文章简述了如何从Objective-C向Swift过渡。话不多说,开门见山。
注意:本文讨论的开发环境为Xcode 6 beta 2版本。
单一文件结构 VS 接口-实现
最值得一提的一大改动便是在Objective-C中“[接口].h/[实现].m”这种文件结构被取缔了。
其实我本人是很支持这种文件结构的,因为通过接口文件来获取及共享类特性的方式相当安全而且简单,不过现在不得不面对它不复存在的现实了。
在Swift中并不存在接口与实现分割成两个文件的现象,我们仅需要依靠实现来构建一个类就行了(并且在写的时候甚至不可能添加关于可访问性的修改)。
如果对于这一改动感到无法忍受的话应注意以下事项:
最为明显的:靠直觉。
我们可以借助漂亮的文档来提高类的可读性。举个例子,我们可以把所有想作为public的要素全部挪到文件开头去,也可以采用扩展来区分public和private。
另一个很实用的办法就是在private的方法和变量命名前加一个下划线‘_'作为前缀。
下面是混合了以上两种方案的示例:
extension&DataReader&{
&&&&var&data&{&}
&&&&func&readData(){
&&&&&&&&var&data&=&_webserviceInteraction()
//&Private&implementation
class&DataReader:&NSObject&{
&&&&let&_wsURL&=&NSURL(string:&"")
&&&&func&_webserviceInteraction()-&String{
&&&&&&&&//&...
虽然我们没办法修改类中各元素的可见性,不过我们可以试着让某些访问变得“困难一些”。
一个特殊的方法就是使用嵌套类来把private部分隐藏起来(至少是自动的隐藏),下面是例子:
import&UIKit
class&DataReader:&NSObject&{
&&&&//&Public&***********************
&&&&var&data:String?{
&&&&&&&&get{return&private.internalData}
&&&&init(){
&&&&&&&&private&=&DataReaderPrivate()
&&&&func&publicFunction(){
&&&&&&&&private.privateFunc()
&&&&//&Private&**********************
&&&&var&private:DataReaderPrivate
&&&&class&DataReaderPrivate&{
&&&&&&&&var&internalData:String?
&&&&&&&&&&
&&&&&&&&init(){
&&&&&&&&&&&&internalData&=&"Private&data!"
&&&&&&&&&&
&&&&&&&&func&privateFunc&(){}
我们将private的实现放入一个private常量的实例中,然后用“正常”的类的实现来充当接口。不过private部分并非会真正的隐藏起来,只不过在访问的时候需要加上一个private关键字:
let&reader&=&DataReader()
reader.private.privateFunc()
问题来了:仅是为了最后要将这些private的部分隐藏起来,就要把代码写得这样怪异值得吗?
我的建议是在可见性的修改出来之前(苹果正在忙这个事),我们还是采用详细的文档或者多少用一点扩展来完成这个事。
常量和变量
在写Objective-C的时候我会很少的使用到const关键字,甚至于我知道有的数据时不会变的。然而在Swift中苹果建议开发者们多花点心思在使用常量(let)而不是变量(var)上。所以请注意要弄明白你的变量的具体要做什么。你会使用常量的频繁度将是你从未想象过的。
更加简化的写法
来看一下下面的两行代码,比较一下有何不同:
let&wsURL:NSURL&=&NSURL(string:"");
let&wsURL&=&NSURL(string:"")
在我最开始接触Swift的前两个星期,我强迫自己不要在每一行代码最后都添加分号(不过现在写Objective-C的时候我不会加分号了)。
类型推断可以直接根据变量的定义为其指派类型,相比较Objective-C这类冗杂的语言来说,在这里倒是可圈可点。
我们应该使用一致的命名方式,否则其他的开发者(包括你自己)就很难通过极其糟糕的命名来推测其类型:
let&a&=&something()
更加合理的命名是这样的:
let&a&=&anInt()
还有一个改动就是关于括弧号,他们不再需要配对了:
if&(a&&&b){}
&&&&&vs&&&
if&a&&&b&{}
不过请记住,我们在括号中间写入的部分会被认为是一个表达式,在这里并不代表这样写总是对的。在变量绑定时我们不能像下面这样使用括号:
if&(let&x&=&data){}&//&Error!&
if&let&x&=&data&{}&//&OK!
使用类型判断和删除分号及括号并不完全必要,不过我们可以考虑一下用以上建议的方式来写Swift代码,这样的话会提高代码的可读性并且减少一些输入量。
有多少次我们困惑与函数的返回值该如何设置?我曾经使用过NSNotFound, -1, 0,自定义的返回值来表示返回为空。
现在可选值的出现很好的解决了返回值为空的问题,我们仅需要在数据类型的后面添加一个问号就可以了。
我们可以这样写:
class&Person{
&&&&let&name:String
&&&&let&car:Car?&//&Optional&value
&&&&init(name:String){
&&&&&&&&self.name&=&name
//&ACCESSING&THE&OPTIONAL&VALUE&***********
var&Mark&=&Person(name:"mark")
//&use&optional&binding&
if&let&car&=&Mark.car&{
&&&&car.accelerate()
//&unwrap&the&value
Mark.car?.accelerate()
这是个用了可选值来描述“某人有一辆车”的例子,它表示car这一特征可以是没有的,因为这表示某人没有车。
然后我们可以用optional binding或者unwrap来取得它的值。
如果对于一个属性没有设定为可选值,我们又没有为其赋值的话,编译器会立马不爽快的。
一旦初始化了之后便没有设定非可选属性的机会了。
所以我们应该事先考虑一下类的属性与其它部分的关系,以及在类进行实例化的时候它们会发生什么变化。
这些改进彻底的改变了构思一个类的方式。
可选值的拆包
你会发现可选值这个东西难以理喻,因为你不会理解为什么编译器会提示你在使用之前对其进行拆包。
我建议你把可选值当做一个结构体(当做结构体的话会好理解一些),其中包括了一个你所设定的值。不过外面包裹了其他东西(wrap)。如果里面的值有定义,你就可以进行拆包(unwrap)然后得到你所想得到的值。否则你就得到一个空值(nil)。
使用感叹号"!"来进行强制拆包而不管其中的值是否有定义,这样做是有风险的,因为如果里面的值没有定义的话应用会崩掉。
经过多年的Objective-C和Cocoa代码编写,我想大部分人都对使用委托模式养成了一种嗜好。注意了!我们还是可以继续保留这种嗜好的,下面是一个非常简单的例子:
@objc&protocol&DataReaderDelegate{
&&&&@optional&func&DataWillRead()
&&&&func&DataDidRead()
class&DataReader:&NSObject&{
&&&&var&delegate:DataReaderDelegate?
&&&&var&data:NSData?
&&&&func&buildData(){
&&&&&&&&&&
&&&&&&&&delegate?.DataWillRead?()&//&Optional&method&check
&&&&&&&&data&=&_createData()
&&&&&&&&delegate?.DataDidRead()&&&&&&&//&Required&method&check
这里我们使用了一个简单的@optional来替换了使用respondToSelector检测委托方法是否存在。
delegate?.DataWillRead?()
请注意我们在协议之前必须加@obj前缀,因为后面使用了@optional。同时编译器也会在这里报一个警告的消息以防你没有加上@obj。
要实现协议的话,我们需要构建一个类来实现它然后用曾经在OC上用过的方式来指派。
class&ViewController:&UIViewController,&DataReaderDelegate&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&override&func&viewDidLoad()&{
&&&&&&&&super.viewDidLoad()
&&&&&&&&&&
&&&&&&&&let&reader&=&DataReader()
&&&&&&&&reader.delegate&=&self
&&&&func&DataWillRead()&{...}
&&&&func&DataDidRead()&{...}
目标-动作模式
另一常用的设计模式:目标-动作模式。我们仍然同样可以像在OC中使用它那样在Swift中实现它。
class&ViewController:&UIViewController&{
&&&&@IBOutlet&var&button:UIButton
&&&&override&func&viewDidLoad()&{
&&&&&&&&super.viewDidLoad()
&&&&&&&&&&
&&&&&&&&button.addTarget(self,&action:&"buttonPressed:",&forControlEvents:&UIControlEvents.TouchUpInside)
&&&&func&buttonPressed(sender:UIButton){...}
这里唯一不同的地方就是如何定义一个selector选择器。我们可以变形使用像下面这样的字符串来写方法原型:
Selector("buttonPressed:")
简直又爱又恨。单件模式依旧是设计模式中最为常用的模式之一。
我们可以用GCD和dispatch_once来实现它,当然还可以用let关键字来实现线程安全。
class&DataReader:&NSObject&{
&&&&class&var&sharedReader:DataReader&{
&&&&&&&&&&
&&&&&&&&struct&Static{
&&&&&&&&&&&&static&let&_instance&=&DataReader()
&&&&&&&&&&
&&&&&&&&return&Static._instance
我们来快速浏览一下这段代码:
1、sharedReader是一个静态的复合属性(我们也可以替换为方法)。
2、静态属性不允许在类被实现的时候重构,所以由于内部类型是被允许的,我们可以再这里加入一个结构体。
3、_instance是一个常量,它不会被重写而且保证线程安全。
可以参考下面DataReader单例的用法:
DataReader.sharedReader
结构和枚举
Swift中的结构和枚举简直神乎其神,你根本不会在其他的语言里面找到像它们这样的。
它们支持方法:
struct&User{
&&&&//&Struct&properties
&&&&let&name:String
&&&&let&ID:Int
&&&&//&Method!!!
&&&&func&sayHello(){
&&&&&&&&println("I'm&"&+&self.name&+&"&my&ID&is:&\(self.ID)")
let&pamela&=&User(name:&"Pamela",&ID:&123456)
pamela.sayHello()
如你所见在这里的结构体使用了初始化,而且这个是Swift自动创建的(我们可以添加一些自定的实现)。
枚举类型的语法比起我们用过的会稍难。
它的定义需要用到关键字case:
enum&Fruit&{&
&&case&orange
&&case&apple
而且枚举并不局限于int型:
enum&Fruit:String&{&
&&case&.orange&=&"Orange"
&&case&.apple&=&"Apple"
而且还可以用的更复杂一些:
enum&Fruit{
&&&&//&Available&Fruits
&&&&case&orange
&&&&case&apple
&&&&//&Nested&type
&&&&struct&Vitamin{
&&&&&&&&var&name:String
&&&&//&Compound&property
&&&&var&mainVitamin:Vitamin&{
&&&&switch&self{
&&&&case&.orange:
&&&&&&&&return&Vitamin(name:&"C")
&&&&&&&&&&
&&&&case&.apple:
&&&&&&&&return&Vitamin(name:&"B")
let&Apple&=&Fruit.apple
var&Vitamin&=&Apple.mainVitamin
在上面我们为Fruit枚举类添加了一个内部类型Vitamin和一个复合的mainVitamin,并且这样的结构还可以根据枚举的值来进行初始化里面的元素……是不是已经感到眼花缭乱了?
可变与不可变类
在OC中我们总会用到可变以及不可变类,举个例子?NSArray和NSDictionary。在Swift里面我们不在像这样来区分数据了,只需要用常量和变量的定义来替代。
数据变量是可以变的,而数组常量的值不可更改。所以请记下这个公式:
“let = immutable. var = mutable”.
我非常喜欢块的语法,因为它相当简单而且好记。
顺带提一下,因为有多年Cocoa的变成习惯,所以有时候我会偏爱于用块来替代简单的委托作业。这是很灵活快捷的方式,而且非常实用。
Swift中与块相对的是闭包。闭包的作用极为强大而且苹果在将其简单化上做得很棒,很容易就可以实现。
官方文档里的示例只能说让我无言以对。
它是这样定义的:
reversed&=&sort(names,&{&(s1:&String,&s2:&String)&-&&Bool&in
&&&&return&s1&&&s2
然后是这样重构的:
reversed&=&sort(names,&&)
所以,由于类型判断的存在,我们能以不同的方式来实现一个闭包、速写参数($0, $1)和直接操作函数(&)。
在这篇文章里我打算遍历一下闭包的用法,不过此前我想对如何获取闭包中的值说几句。
在OC里面,我们定义一个变量像_block这样,以方便我们想预备将它压入块。不过在闭包里面这些都没有必要。
我们可以使用和修改周围的值。事实上闭包被设计得非常聪明,足够它获取外部的元素来给内部使用。每个被获取的元素会作为拷贝或者是引用。如果闭包会修改它的值则创建一个引用,否则就生成一份拷贝。
如果闭包引用了一个包含或调用了闭包本身的实例,我们就会进入一个循环强引用。
来看一下例子:
class&Person{
&&&&var&age:Int&=&0
&&&&@lazy&var&agePotion:&(Int)&-&&Void&=&{
&&&&&&&&(agex:Int)-&Void&in
&&&&&&&&&&&&self.age&+=&agex
&&&&func&modifyAge(agex:Int,&modifier:(Int)-&Void){
&&&&&&&&modifier(agex)
var&Mark:Person?&=&Person()
Mark!.modifyAge(50,&Mark!.agePotion)
Mark&=&nil&//&Memory&Leak
这个agePotion闭包引用了它本身,而对当前的实例保证了强引用。同时实例保持了一个队闭包的引用。BOOM~~~我们进入了一个循环强引用。
为了避免这种情况我们需要使用获取列表Capture List.??,??这个列表维护了我们想使用的实例的无主弱引用。语法十分简单,只需要在闭包定义前添加 [unowned/strong self]就行,然后你会得到一个无主的弱引用来替代以前的强引用。
@lazy&var&agePotion:&(Int)&-&&Void&=&{
&&&&&[unowned&self](agex:Int)-&Void&in
&&&&&&&&&self.age&+=&agex
无主弱引用
在OC里面我们知道弱引用是怎么运作的。在Swift里面也一样,基本没什么变化。
所以什么是无主引用呢。我仔细的看了看这个关键词的介绍,因为它很好的说明了类间的关系的定义。
让我们来简单的描述一下人Person与银行账户BankAccount间的关系:
1、一个人可以拥有一个银行账户(可选)。
2、一个银行账户属于一个人(必须)。
We&can&describe&this&relation&with&code:&
class&Person{
&&&&let&name:String
&&&&let&account:BankAccount!
&&&&init(name:String){
&&&&&&&&self.name&=&name
&&&&&&&&self.account&=&BankAccount(owner:&self)
class&BankAccount{
&&&&let&owner:Person
&&&&init(owner:Person){
&&&&&&&&self.owner&=&owner
这写关系会创建一个引用循环。第一种解决方案添加了一个弱引用给“BankAccount.owner”属性。不过还用了一个无主引用作为约束:这个属性必须有一个值,不能为空(之前的列表里的第二点令人满意)。
好了,关于无主引用没有更多要说的了。其实它恰好就像一个没有为所指引用增加作用的弱引用,不过为其保证了一个不为空的值。
最后你会发现,在Swift耗费的实验和测试的次数越多,就会越清晰的明白其价值所在。
已收藏 取消
糖果果 DevStore编辑
简介:Too Young Too Simple
可能喜欢的文章
客服邮箱:
开发者交流群:
运营交流群:
深圳尺子科技有限公司
深圳市南山区蛇口网谷万海大厦C栋504
Copyright (C) 2015 DevStore. All Rights ReservedSwift 与 Objective-C 的兼容能力使你可以在同一个工程中同时使用两种语言。你可以用这种叫做&mix and match&的特性来开发基于混合语言的应用,可以用 Swfit 的最新特性实现应用的一部分功能,并无缝地并入已有的 Objective-C 的代码中。
Mix and Match 概述
Objective-C 和 Swift 文件可以在一个工程中并存,不管这个工程原本是基于 Objective-C 还是 Swift。你可以直接往现有工程中简单地添加另一种语言的源文件。这种自然的工作流使得创建混合语言的应用或框架 target,与用单独一种语言时一样简单。
混合语言的工作流程只有一点点区别,这取决于你是在写应用还是写框架。下面描述了普通的用两种语言在一个 target 中导入模型的情况,后续章节会有更多细节。
在同个应用的 target 中导入
如果你在写混合语言的应用,可能需要用 Swift 代码访问 Objective-C 代码,或者反之。下面的流程描述了在非框架 target 中的应用。
将 Objective-C 导入 Swift
在一个应用的 target 中导入一些 Objective-C 文件供 Swift 代码使用时,你需要依赖与 Objective-C 的桥接头文件(bridging header)来暴露给 Swift。当你添加 Swift 文件到现有的 Objective-C 应用(或反之)时,Xcode 会自动创建这些头文件。
如果你同意,Xcode 会在源文件创建的同时生成头文件,并用 product 的模块名加上&-Bridging-Header.h&命名。关于 product 的模块名,详见&。
你应该编辑这个头文件来对 Swift 暴露出 Objective-C 代码。
在同一 target 中将 Objective-C 代码导入到 Swift 中
1) 在 Objective-C 桥接头文件中,import 任何你想暴露给 Swift 的头文件,例如:
// OBJECTIVE-C
#import &XYZCustomCell.h&
#import &XYZCustomView.h&
#import &XYZCustomViewController.h&
2) 确保在&Build Settings&中 Objective-C 桥接头文件的&build setting&是基于 Swfit 编译器,即&Code Generation&含有头文件的路径。这个路径必须是头文件自身的路径,而不是它所在的目录。
这个路径应该是你工程的相对路径,类似&Info.plist&在&Build Settings&中指定的路径。在大多数情况下,你不需要修改这个设置。
在这个桥接头文件中列出的所有 public 的 Objective-C 头文件都会对 Swift 可见。之后当前 target 的所有 Swift 文件都可以使用这些头文件中的方法,不需要任何 import 语句。用 Swift 语法使用这些 Objective-C 代码,就像使用系统自带的 Swift 类一样。
let myCell = XYZCustomCell()
myCell.subtitle = &A custom cell&
将 Swift 导入 Objective-C
向 Objective-C 中导入Swift 代码时,你依赖 Xcode 生成的头文件来向 Objective-C 暴露 Swift 代码。这是自动生成 Objective-C 头文件,它包含了你的 target 中所有 Swift 代码中定义的接口。可以把这个 Objective-C 头文件看作 Swift 代码的&umbrella header。它以 product 模块名加&-Swift.h&来命名。关于 product 的模块名,详见。
你不需要做任何事情来生成这个头文件,只需要将它导入到你的 Objective-C 代码来使用它。注意这个头文件中的 Swift 接口包含了它所使用到的所有 Objective-C 类型。如果你在 Swift 代码中使用你自己的 Objective-C 类型,确保先将对应的 Objective-C 头文件导入到你的 Swift 代码中,然后才将 Swift 自动生成的头文件导入到 Objective-C .m 源文件中来访问 Swift 代码。
在同一 target 中将 Swift 代码导入到 Objective-C 中
在相同 target 的 Objective-C .m 源文件中,用下面的语法来导入Swift 代码:
// OBJECTIVE-C
#import &ProductModuleName-Swift.h&
target 中任何 Swift 文件将会对 Objective-C .m 源文件可见,包括这个 import 语句。关于在 Objective-C 代码中使用 Swift 代码,详见&。
导入到 Swift
导入到 Swift
Swift 代码
不需要import语句
Objective-C 代码
不需要import语句;需要 Objective-C `umbrella头文件
#import &Header.h&
在同个 Framework 的 target 中导入
如果你在写一个混合语言的框架,可能会从 Swift 代码访问 Objective-C 代码,或者反之。
将 Objective-C 导入 Swift
要将一些 Objective-C 文件导入到同个框架 target 的 Swift 代码中去,你需要将这些文件导入到 Objective-C 的&umbrella header来供框架使用。
在同一 framework 中将 Objective-C 代码导入到 Swift 中
确保将框架 target 的&Build Settings & Packaging & Defines Module&设置为&Yes。然后在你的&umbrella header&头文件中导入你想暴露给 Swift 访问的 Objective-C 头文件,例如:
// OBJECTIVE-C
#import &XYZ/XYZCustomCell.h&
#import &XYZ/XYZCustomView.h&
#import &XYZ/XYZCustomViewController.h&
Swift 将会看到所有你在&umbrella header&中公开暴露出来的头文件,框架 target 中的所有 Swift 文件都可以访问你 Objective-C 文件的内容,不需要任何 import 语句。
let myCell = XYZCustomCell()
myCell.subtitle = &A custom cell&
将 Swift 导入 Objective-C
要将一些 Swift 文件导入到同个框架的 target 的 Objective-C 代码去,你不需要导入任何东西到&umbrella header&文件,而是将 Xcode 为你的 Swift 代码自动生成的头文件导入到你的 Obj .m 源文件去,以便在 Objective-C 代码中访问 Swift 代码。
在同一 framework 中将 Swift 代码导入到 Objective-C 中
确保将框架 target 的&Build Settings & Packaging&中的&Defines Module&设置为&Yes。用下面的语法将 Swift 代码导入到同个框架 target 下的 Objective-C .m 源文件去。
// OBJECTIVE-C
#import &ProductName/ProductModuleName-Swift.h&
这个 import 语句所包含的 Swift 文件都可以被同个框架 target 下的 Objective-C .m 源文件访问。关于在 Objective-C 代码中使用 Swift 代码,详见&。
导入到 Swift
导入到 Swift
Swift 代码
不需要import语句
Objective-C 代码
不需要import语句;需要 Objective-C `umbrella头文件
#import &Header.h&
导入外部 Framework
你可以导入外部框架,不管这个框架是纯 Objective-C,纯 Swift,还是混合语言的。import 外部框架的流程都是一样的,不管这个框架是用一种语言写的,还是包含两种语言。当你导入外部框架时,确保&Build Setting & Pakaging & Defines Module&设置为Yes。
用下面的语法将框架导入到不同 target 的 Swift 文件中:
import FrameworkName
用下面的语法将框架导入到不同 target 的 Objective-C .m 文件中:
// OBJECTIVE-C
@import FrameworkN
导入到 Swift
导入到 Objective-C
任意语言框架
import FrameworkName
@import FrameworkN
在 Objective-C 中使用 Swift
当你将 Swift 代码导入 Objective-C 文件之后,用普通的 Objective-C 语法使用 Swift 类。
// OBJECTIVE-C
MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
[swiftObject swiftMethod];
Swift 的类或协议必须用&@Objective-C attribute&来标记,以便在 Objective-C 中可访问。这个 attribute 告诉编译器这个 Swift 代码可以从 Objective-C 代码中访问。如果你的 Swift 类是 Objective-C 类的子类,编译器会自动为你添加&@Objective-C attribute。详见&。
你可以访问 Swift 类或协议中用&@Objective-C attribute&标记过东西,只要它和 Objective-C 兼容。不包括一下这些 Swift 独有的特性:
Generics - 范型
Tuples - 元组
Enumerations defined in Swift - Swift 中定义的枚举
Structures defined in Swift - Swift 中定义的结构体
Top-level functions defined in Swift - Swift Swift 中定义的顶层函数
Global variables defined in Swift - Swift 中定义的全局变量
Typealiases defined in Swift - Swift 中定义的类型别名
Swift-style variadics - Swift风格可变参数
Nested types - 嵌套类型
Curried functions - 柯里化后的函数
例如带有范型类型作为参数,或者返回元组的方法不能在 Objective-C 中使用。
为了避免循环引用,不要将 Swift 代码导入到 Objective-C 头文件中。但是你可以在 Objective-C 头文件中前向声明(forward declare)一个 Swift 类来使用它,然而,注意不能在 Objective-C 中继承一个 Swift 类。
在 Objective-C 头文件中引用 Swift 类
这样前向声明 Swift 类:
// OBJECTIVE-C
// MyObjective-CClass.h
@class MySwiftC
@interface MyObjective-CClass : NSObject
- (MySwiftClass *)returnSwiftO
Product 模块命名
Xcode 为 Swift 代码生成的头文件的名称,以及 Xcode 创建的 Objective-C 桥接头文件名称,都是从你的 product 模块名生成的。默认你的 product 模块名和 product 名一样。然而,如果你的 product 名有特殊字符(nonalphanumeric,非数字、字母的字符),例如点号,那么它们会被下划线(_)替换之后作为你的 product 模块名。如果 product 名以数字开头,那么第一个数字会用下划线替换掉。
你可以给 product 模块名提供一个自定义的名称,Xcode 会用这个名称来命名桥接的和自动生成的头文件。你只需要在修改在build setting&中的&Product Module Name&即可。
问题解决提示
把 Swift 和 Objective-C 文件看作相同的代码集合,并注意命名冲突;
如果你用框架,确保&Build Setting & Pakaging & Defines Module&设置为&Yes;
如果你使用 Objective-C 桥接头文件,确保在&Build Settings&中 Objective-C 桥接头文件的&build setting&是基于 Swfit 编译器,即&Code Generation&含有头文件的路径。这个路径必须是头文件自身的路径,而不是它所在的目录;
Xcode 使用你的 product 模块名,而不是 target 名来命名 Objective-C 桥接头文件和为 Swift 自动生成的头文件。详见&;
为了在 Objective-C 中可用, Swift 类必须是 Objective-C 类的子类,或者用&@Objective-C&标记;
当你将 Swift 导入到 Objective-C 中时,记住 Objective-C 不会将 Swift 独有的特性翻译成 Objective-C 对应的特性。详见列表;
如果你在 Swift 代码中使用你自己的 Objective-C 类型,确保先将对应的 Objective-C 头文件导入到你的 Swift 代码中,然后才将 Swift 自动生成的头文件 import 到 Objective-C .m 源文件中来访问 Swift 代码。Objective-C 关于静态方法与实例方法的转载
objective-c中非常重要的语法知识,在此归纳总结一下。
类方法,也称静态方法,指的是用static关键字修饰的方法。此方法属类本身的方法,不属于类的某一个实例(对象)。类方法中不可直接使用实例变量。其调用方式有三种:可直接调用、类名.方法名、对象名.方法名。实例方法指的是不用static关键字修饰的方法。每个实例对象都有自身的实例方法,互相独立,不共享一个。其调用方式只能是对象名.方法名。
用修饰符static声明的方法为静态方法,不用修饰符static声明的方法为实例方法。不管类生成或未生成对象,类的静态方法都可以被使用,使用格式为:类名.静态方法名。静态方法只能使用该静态方法所在类的静态数据成员和静态方法。这是因为使用静态方法时,该静态方法所在类可能还没有对象,即使有对象,由于用类名.静态方法名方式调用静态方法,静态方法没有this指针来存放对象的地址,无法判定应访问哪个对象的数据成员。在类创建对象后,实例方法才能被使用,使用格式为:对象名.实例方法名。实例方法可以使用该方法所在类的所有静态成员和实例成员。
何时用静态方法,何时用实例方法?
先说实例方法,当你给一个类写一个方法,如果该方法需要访问某个实例的成员变量时,那么就将该方法定义成实例方法。一类的实例通常有一些成员变量,其中含有该实例的状态信息。而该方法需要改变这些状态。那么该方法需要声明成实例方法。
静态方法正好相反,它不需要访问某个实例的成员变量,它不需要去改变某个实例的状态。我们把该方法定义成静态方法。
关于静态方法和实例方法的一些误区。
一、静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存。
事实上,方法都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。
二、静态方法在堆上分配内存,实例方法在堆栈上。
事实上所有的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。
三、实例方法需要先创建实例才可以调用,比较麻烦,静态方法不用,比较简单。
事实上如果一个方法与他所在类型的实例无关,那么它就应该是静态的,决不会有人把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。实际上上你可以把所有的实例方法都写成静态的,将实例作为参数传入即可。
有些方法看似与所在的实例无关,如pare方法,但实际上每一个实现这个接口的类都只会负责自己类型实例的比较,这是C#1.x规范中没有泛型所带来的历史遗留问题。
大部分静态方法是与类的实例有关的,如各种Parse方法,他做成静态的原因是他没有实例作为参数。其他的大多是出于语义或者其他目的的考虑。
第一种方式, 声明实例,调用实例方法
当一个类有多个实例,例如学生这个类,实例可以有学生甲,学生乙,学生丙,等等,我们就用第一种方式。在多线程的情况下,只要每个线程都创建自己的实例,那么第一种方法通常是线程安全的。
第二种方式,通过一个静态的实例,去调用实例方法
这种情况比较特殊,通常是整个程序里该类唯一的一个实例,我们通过调用该实例的实例方法来改变该实例的某些状态。这一个实例在多线程的情况下,通常是线程不安全的。除非我们给这个实例加锁。防止其他线程访问该实例。
第三种方式,直接调用静态方法
这种情况下静态方法不需要去改变某个实例的状态。只要得到少量的参数就可完成既定事情。比如判断一个文件是否存在,只要给个文件路径和文件名,就能知道该文件是否存在。
调用一个类的静态方法需不需要release?(内存管理)(面试题)
我个人认为,静态成员方法不需要对象,不需要release。
注:其实静态成员方法也是有对象的,叫做类对象,但这个是在第一次访问类成员时触发将其加载到内存的,而且该类对象只在程序立闭时,才会释放,并不由程序本身控制。
有三个概念要分清:类、实例和对象,类本身加载到内存(可能是代码段的内存,不是堆内存,也不是栈内存),可以叫做一个对象;创建一个类的实例,这个实例可以叫做一个对象,所以就有类对象和实例对象之分了,类对象就是一张图纸,实例对象是按类对象造出的一H楼,确实都是实实在在存在的东西,所以叫对象,只不过性质不同,一个是图纸,一个是按图纸造出来的楼房。
其实,我也很想知道,这是哪家公司的面试题,搞得这么不严谨。
从这一句话中,可以有两种理解,一是类的静态方法中返回的对象是否需要release;二是调用实例方法需要release吗?就是说要调用release,需要先alloc+init,这时才能调用实例对象的方法,使用完了,要release;那么直接调用类的静态方法,是否需要release类本身的对象。
从以上分析,能得出这样的结论:该公司刚接触objectiv-c;该公司面试的人没有真正熟练和掌握objective-c,也是刚入门的家伙;最后,可能是面试的人说错了,或此贴提问的人写错了。
这个好帖子我要马克一下,今天碰到&静态方法&一下子没反应过来,楼主你可帮了我大忙了,那句&静态方法不需要release因为没有对象&也给了我启发,有时候学多了很容易忘记最基础的思想。
注:确有同感,早些年,无论是学c++,还是objective-c,又或是java,时间久了,用一些东西成习惯了,就不知道是啥意思了,所以得常反刍,才易消化。
就象学五笔,用五笔,N年之后,好多字不会拆,但常用的能打出来,其实是成了习惯了,而忘了规律。
再比如,你要教小孩子10以内的加减法,看看怎么教才好,或者你还记得当时怎么学的吗?!
20以内的加减法呢?借10法和凑10法,你小时侯学过吗?俺是没学过,就是记住,那时没人教这些个规律,加是正着数,减是倒着数等等,就是卖油翁,手熟尔。
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。

我要回帖

更多关于 objective c 函数调用 的文章

 

随机推荐