Interacting with Objective-C APIs

swift与OC交互

可以使用swift语法使用oc库

初始化

可以使用Swift语法初始化实例。Objective-Cinit到了Swift中, init之前的alloc被去掉, initWith也被去掉。 with后面的参数首字母变成小写, 并且变成了第一个参数的名字。 参数都用小括号括起来,名字和原来一致。

例如OC中:

OBJECTIVE-C

  • UITableView*myTableView=[[UITableViewalloc]initWithFrame:CGRectZerostyle:UITableViewStyleGrouped];

Swift中:

SWIFT

  • letmyTableView:UITableView = UITableView(frame:CGRectZero,style: .Grouped)

不需要调用 alloc; Swift 可以正确的处理这个写法。初始化的时候并没有出现init。

你可以显示的写明实例的类型,也可以不写,swift将自己确定他的类型。

SWIFT

  • letmyTextField = UITextField(frame:CGRect(0.0,0.0,200.0,40.0))

在OC中,UITableView 和 UITextField 实例有类似的方法。你可以使用OC中类似的方法访问他的属性和方法。

为了简明一致, Objective-C和Swift工厂方法中初始化方法一致。例如以下工厂方法例子,OC中:

OBJECTIVE-C

  • UIColor*color=[UIColorcolorWithRed:0.5green:0.0blue:0.5alpha:1.0];

Swift中:

SWIFT

  • letcolor = UIColor(red:0.5,green:0.0,blue:0.5, alpha: 1.0)

访问属性

在swift中使用点语法来访问属性

SWIFT

  • myTextField.textColor = UIColor.darkGrayColor()
  • myTextField.text = "Hello world"
  • ifmyTextField.editing {
  • myTextField.editing = false
  • }

设置和访问属性, 使用属性的名字(不加括号). 注意到darkGrayColor后面有括号,因为darkGrayColor 是UIColor的方法, 而不是属性。

在Objective-C中, 一个没有形参有返回值的方法可以被认为是一个 getter,可以和getter一样的语法被调用。在swift中不是这样,只有用 @property 语法声明的才被认为是属性。 

方法的调用

Swift调用 Objective-C 的方法, 使用点语法。

Objective-C方法转换成Swift方法时, OC方法的第一部分变成方法的名字,出现在括号的外面。第一个形参出现在括号的里面,没有名字。其余的对应形参的名字,所有的都要列出来,不能被省略。

例如 Objective-C 中:

OBJECTIVE-C

  • [myTableViewinsertSubview:mySubviewatIndex:2];

Swift中:

SWIFT

  • myTableView.insertSubview(mySubview,atIndex:2)

调用的方法没有形参,括号不能被省略。

SWIFT

  • myTableView.layoutIfNeeded()

id 兼容

Swift支持一种叫做  AnyObject 的协议类型,代表是任意类型的对象, 对应 Objective-C中的id。 AnyObject 协议允许使用在使用类型安全的Swift 语言同时兼容无类型对象的灵活性。Swift 把id 对应为AnyObject。

例如, 同id一样, 你可以把任意类型的对象赋值给AnyObject类型的常量和变量。

SWIFT

  • varmyObject:AnyObject = UITableViewCell()
  • myObject = NSDate()

你可以调用OC的方法和属性而不必关心他的类型,但是方法要使用 @objc 属性说明。

SWIFT

  • letfutureDate = myObject.dateByAddingTimeInterval(10)
  • lettimeSinceNow = myObject.timeIntervalSinceNow

因为,只有的运行的时候才能够直到 AnyObject 的类型, 因此容易产生错误。 例如,下面这个例子在运行时会产生错误。

SWIFT

  • myObject.characterAtIndex(5)
  • // crash, myObject does't respond to that method

可以使用Swift中得optionals 来排除错误。当你使用AnyObject调用OC中得方法时,实际上使用的是隐含的unwrapped optional。可以使用?来调用 AnyObject 中得方法。访问属性也可以用这个方法。

例如,下面的例子 length 属性 和 characterAtIndex: 方法不存在与 NSDate 对象中。 myLength类型变成Int?, 被置为 nil。你可以使用 iflet 有条件的展开方法的返回值。

SWIFT

  • letmyLength = myObject.length?
  • letmyChar = myObject.characterAtIndex?(5)
  • ifletfifthCharacter = myObject.characterAtIndex(5) {
  • println("Found\(fifthCharacter) at index 5")
  • }

 Swift中, AnyObject 映射成具体的类型不能保证一定会成功,因此会返回一个optional 值,你可以检查这个值看是否成功。

SWIFT

  • letuserDefaults = NSUserDefaults.standardUserDefaults()
  • letlastRefreshDate:AnyObject? = userDefaults.objectForKey("LastRefreshDate")
  • ifletdate = lastRefreshDate as? NSDate {
  • println("\(date.timeIntervalSinceReferenceDate)")
  • }

当然,如果你确定这个类型能转换成功,可以强制使用as。

SWIFT

  • letmyDate = lastRefreshDate as NSDate
  • lettimeInterval = myDate.timeIntervalSinceReferenceDate

使用 nil

在OC中,指向对象的指针有可能是nilI。 Swift中所有的值,包括结构体,和对象的指针都要保证是non–nil。 对于可能为nil的声明为optional。 如果一个值不存在,为nil。

因为OC不能保证对象是非nil的,因此swift把所有从OC导入的类的 classes in argument types 和返回值都认为是optional的。在使用之前要确定是不是nil。

如果确定不为nil,最好也check一下。

扩展

 Swift 扩展类似于 Objective-C 类别。扩展类,结构体,枚举类型 ,也包括已经在Objective-C中定义的。系统和自己定义的类型都可以被扩展。 Simply 导入OC定义的module, 名字和OC中得相同。

下面的例子扩展了 UIBezierPath 类。

SWIFT

  • extensionUIBezierPath {
  • convenienceinit(triangleSideLength:Float,origin:CGPoint) {
  • self.init()
  • letsquareRoot = Float(sqrt(3))
  • letaltitude = (squareRoot *triangleSideLength) / 2
  • moveToPoint(origin)
  • addLineToPoint(CGPoint(triangleSideLength,origin.x))
  • addLineToPoint(CGPoint(triangleSideLength / 2, altitude))
  • closePath()
  • }
  • }

也可以通过扩展来增加computed属性 (包含 class 和 static properties)。  stored properties 不能被添加。

下面例子给 CGRect 增加 computed area 属性:

SWIFT

  • extensionCGRect {
  • vararea:CGFloat {
  • returnwidth * height
  • }
  • }
  • letrect = CGRect(x:0.0,y:0.0,width:10.0, height: 50.0)
  • letarea = rect.area
  • // area: CGFloat = 500.0

可以使用扩展给类增加遵从的协议,协议使用 Swift定义, 可以在 Swift or Objective-C中使用。

不能使用扩展重定义已经有的属性和方法。

Closures

Objective-C 中的block 自动导入成 Swift 中的closures。例如下面的Objective-C block:

OBJECTIVE-C

  • void(^completionBlock)(NSData*,NSError*)=^(NSData*data,NSError*error){/* ... */}

And here’s what it looks like in Swift:

SWIFT

  • letcompletionBlock: (NSData,NSError) -> Void = {data,errorin/* ... */}

Swift closures 和 Objective-C blocks 是兼容的, 你可以把Swift closures 传递给 Objective-C 方法作为参数。 Swift closures 和 functions 类型相同, 所以也可以传入 Swift function。

Closures 和 blocks 有一点不同: Variables are mutable rather than copied. In other words, the behavior of __block in Objective-C is the default behavior for variables in Swift.

对象比较

在 Swift中又两种比较对象的方法:第一种, equality (==), 比较对象的内容. 第二种, identity (===), 比较常量和变量是否指向的是同一个对象。

 Swift 默认 == 比较 NSObject 的子类. 使用 NSObject 中的 isEqual 方法比较。因为NSObject 只进行 identity 比较, 所以你需要自己重写 isEqual: 方法。 可以在swift中实现。

要实现equality, 要有 hash 属性 Object comparison。如果你得类要在dictionary中做key, 要遵从Hashable 协议 并且有 the hashValue 属性。

Swift 类型兼容

如果你定义了一个从NSObject或者其他OC类继承来得swift类, 类自动和Objective-C.兼容。swift编译器会自动把下边的这些步骤做了。如果你从来没有在OC程序里导入swift的类,你也不需要担心兼容性。如果你得swift类没有继承自OC得类并且你想在OC程序中使用这个swift类的话,你可以使用 the @objc attribute。

The @objc attribute 使得你得 Swift API可以在 Objective-C 中使用。换句话说, 你可以在swift的方法,属性和类的前面使用 @objc 属性以便用于 Objective-C 中。 如果你的类继承自 Objective-C class, 编译器会自动给你插入这个属性。 如果类被标记为@objc 属性的话,它的方法还有属性都会被标记上这个属性。 如果你使用了 @IBOutlet@IBAction, or @NSManaged 属性, the @objc 属性也会被添加。 当你使用OC的方法时,属性也会被引入。

当你在 Objective-C中使用 Swift API, 编译器会进行直接翻译。 例如, the Swift API func playSong(name: String)会被导入成Objective-C中的 - (void)playSong:(NSString *)name。但是有例外情况: 在Objective-C中使用Swift initializer, 编译器会在方法的前面加上“initWith”和第一个形参首字母大写后的名字。例如, this Swift initializer init (songName: String, artist: String)被导入为- (instancetype)initWithSongName:(NSString *)songName artist:(NSString *)artist in Objective-C.

Swift 提供 @objc 属性更改在 Objective-C中使用的名字。例如,如果swift类的名字包含了在OC中不能使用的字符的话,可以定义成其他的名字。给swift函数起了一个OC的名字,要遵从selector语法。

SWIFT

  • @objc(Squirrel)
  • classБелка {
  • @objc(initWithName:)
  • init (имя:String) { /*...*/ }
  • @objc(hideNuts:inTree:)
  • funcпрячьОрехи(Int,вДереве:Дерево) { /*...*/ }
  • }

在swift类中使用 @objc(<#name#>) 别名的类, 不需要命名空间。 As a result, this attribute can also be useful when you migrate an archivable Objective-C class to Swift. Because archived objects store the name of their class in the archive, you should use the @objc(<#name#>) attribute to specify the same name as your Objective-C class so that older archives can be unarchived by your new Swift class.

Objective-C Selectors

An Objective-C selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure. You can construct a selector with a string literal, such aslet mySelector: Selector = "tappedButton:". Because string literals can be automatically converted to selectors, you can pass a string literal to any method that accepts a selector.

SWIFT

  • importUIKit
  • classMyViewController:UIViewController {
  • letmyButton = UIButton(frame:CGRect(x:0,y:0,width:100, height: 50))
  • init(nibNamenibNameOrNil:String!,bundlenibBundleOrNil:NSBundle!) {
  • super.init(nibName:nibName,bundle:nibBundle)
  • myButton.targetForAction("tappedButton:",withSender:self)
  • }
  • functappedButton(sender:UIButton!) {
  • println("tapped button")
  • }
  • }

NOTE

The performSelector: method and related selector-invoking methods are not imported in Swift because they are inherently unsafe.

If your Swift class inherits from an Objective-C class, all of the methods and properties in the class are available as Objective-C selectors. Otherwise, if your Swift class does not inherit from an Objective-C class, you need to prefix the symbol you want to use as a selector with the @objc attribute, as described in Swift Type Compatibility.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值