
北京时间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江湖》一书作者。