北京时间2月10日,苹果在面向开发者推送iOS 8.3 Beta的同时,还发布了版本号为6D520o的Xcode 6.3 Beta,其中便包含了iOS 8.3 Beta和OS X v10.10 SDK,并进一步提升了Swift与Objective-C代码的交互性,而Swift业已更新至1.2版本。
从Xcode 6.3 Beta Release Notes看出,Xcode 6.3 Beta包含了很多颇为值得开发者期待的改变,共计50多处改动,同时修改了Objective-C的语法,足见苹果对Swift语言的重视。而其代码迁移工具可以帮助开发者将其代码从Swift 1.1(Xcode 6.1)升级至Swift 1.2(Xcode 6.3),具体执行编辑菜单(Edit)->转换(Convert)-至(To)Swift1.2即可。 具体更新如下:
if let a = foo(), b = bar() where a < b, let c = baz() { }
它允许你测试多种选择,并且包含一个bool判断。当然这种情况不包含嵌套判断。
let x: SomeThing if condition { x = foo() } else { x = bar() } use(x)
这个正常的来说需要var变量用法,尽管这里没有任何修改的操作。
@objc enum Bear: Int { case Black, Grizzly, Polar }导出到Objective-C:
typedef NS_ENUM(NSInteger, Bear) { BearBlack, BearGrizzly, BearPolar };
import Darwin var devNullStat = stat() stat("/dev/null", &devNullStat)
如果一个结构体的元素不能被正确的初始化为0(比如被标记为新的_nonnull标示符时),这个默认的构造器将会终止。
toString(Int.self) // 打印 “Swift.Int" println([Float].self) // 打印 "Swift.Array<Swift.Float>” println((Int, String).self) // 打印 "(Swift.Int, Swift.String)"
func autoreleasepool(@noescape code: () -> ()) { pushAutoreleasePool() code() popAutoreleasePool() }
import Foundation func log(s: String) { println(x) } let ns: NSString = "some NSString" // Okay log(ns) // 错误 // "'NSString' 不能转换为 'String'"为了完成桥接转换,需要用显式转化符标注:
log(ns as String) // succeeds从Swift类型到Objective-C类型的桥接隐式转换依然被允许,比如:
func nsLog(ns: NSString) { println(ns) } let s: String = “some String” nsLog(s) // okay: implicit conversion from String to NSString is still permitted
//以前我们这样写: func assert(predicate : @autoclosure () -> Bool) {… } //现在需要这样写: func assert(@autoclosure predicate : () -> Bool) {… }
func curryUnnamed(a: Int)(_ b: Int) { return a + b } curryUnnamed(1)(2) func curryNamed(first a: Int)(second b: Int) -> Int { return a + b } curryNamed(first: 1)(second: 2)
class A : NSObject { var property: String = "Hello" // 注意: Objective-C 方法 'setProperty:’ // 以前这里“属性”这里是通过setter声明 } extension A { func setProperty(str: String) { } // 错误:方法"setProperty" // 重复声明了Objective-C方法 //'setProperty:' }同样地检查在Objective-C中重写:
class B : NSObject { func method(arg: String) { } // 注意:重写操作 // 这里含有类型:'(String) -> ()' } class C : B { func method(arg: [String]) { } // 错误: 重写的选择器方法含有不匹配的类型'([String]) -> ()' }和协议的适配性一样:
class MyDelegate : NSObject, NSURLSessionDelegate { func URLSession(session: NSURLSession, didBecomeInvalidWithError: Bool){ } // 错误:Objective-C 方法 'URLSession:didBecomeInvalidWithError:' //由方法提供: 'URLSession(_:didBecomeInvalidWithError:)' // 和可选类型的需求方法相冲突: // 'URLSession(_:didBecomeInvalidWithError:)' 在协议 // 'NSURLSessionDelegate' }
struct Point { var x, y: Double } extension Point : Printable { var description: String { return "(\(x), \(y))" } } var p1 = Point(x: 1.5, y: 2.5) println(p1) // prints "(1.5, 2.5)”
let animationCurve = nsafeBitCast(userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue, UIViewAnimationCurve.self)现在可以写为:
let animationCurve = UIViewAnimationCurve(rawValue: userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue)!
class Base { func foo(x: String) -> String? { return x } } class Derived: Base { override func foo(x: String?) -> String { return x! } }
-(void)registerNib:(nonnull UINib *)nib forCellReuseIdentifier:(nonnull SString *)identifier; -(nullable UITableViewCell *)cellForRowAtIndexPath:(nonnull SIndexPath)indexPath; @property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;这个nullability标示符影响了Objective-C API在Swift的可选类型值,nonnull标示符标示的类型将会以非可选的类型的导入,这个用来替代隐式解封可选类型如(e.g., UINib!)。而nullable标示符标示的类型则会以可选类型导入(如UITableViewCell?),所以下面的API在Swift中表现如下:
func registerNib(nib: UINib, forCellReuseIdentifier identifier: String) func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell? var backgroundView: UIView?
void enumerateStrings(__nonnull CFStringRef (^ __nullable callback)(void));这里,它自身的回调函数是nullable的,但是它的回调函数的返回类型为nonnull,所以这个API在Swift以如下方式使用:
func enumerateStrings(callback: (() -> CFString)?)总的来说,可空特性标示符有三种,可以用双下划线(用在任何指针类型),或者没有下划线的(用在Objective-C属性,方法结果类型或者方法参数类型)。
Type qualifier spelling |
Objective-C property/method spelling |
Swift view |
Meaning |
__nonnull |
nonnull |
Non-optional, 如: UINib |
该值永远不会为nil(有一种例外是可能参数传递时传入的消息为空) |
__nullable |
nullable |
Optional, 如:UITableViewCell? |
该值可能为nil |
__null_unspecified |
null_unspecified |
隐式解封可选类型如, NSDate! |
不确定该值是否为空(很少见) |
#pragma clang assume_nonnull begin // … -(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier; -(nullable UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath)indexPath; @property (nonatomic, readwrite, retain, nullable) UIView *backgroundView; // … #pragma clang assume_nonnull end
@property (nonatomic, retain, null_resettable) UIColor *tintColor;这样的API在Swift使用隐式强制解封的方法使用:
var tintColor: UIColor!
void executeImmediately(__attribute__((noescape)) void (^callback)(void);将被影射到Swift为:
func executeImmediately(@noescape callback: () -> Void)
作者简介:
王芳杰 目前就职于叠拓信息技术有限公司,担任叠拓NGN中国人力资源培养经理、叠拓NGN中国售前经理,《老码说编程之玩转Swift江湖》一书作者。