兼容id
类型
Swift包含一个叫AnyObject
的协议,与Objective-C中的id
类似,可以表示任意类型的对象。AnyObject
协议允许你在利用无类型对象的灵活性的同时保持类型安全。
你可以给AnyObject
类型的变量赋任意的值:
var myObject: AnyObject = NSData()
可以直接方法AnyObject
类型对象的任意属性和方法,而不需要进行强制类型转换。
let dateDescription = myObject.description
let timeSinceNow = myObject.timeIntervalSinceNow
由于AnyObject
类型的变量的类型需要到运行时才能确定,因此可能会导致不安全的代码。特别是你可以访问一个不存在的属性或者方法,它只是在运行时报错。
myObject.characterAtIndex(5) //crash,myObject doesn't respond to that method
在进行类型转换的时候,不一定转换成功,因此Swift返回的是一个Optional值。你可以检查是否转换成功。
let userDefaults = NSUserDefaults.standardUserDefaults()
let lastRefreshDate: AnyObject? = userDefault.objectForKey(@H_301_40@"LastRefreshDate")
if let date = lastRefreshDate as? NSDate {
println("\(date.timeIntervalSinceReferenceDate)")
}
如果你能够确定对象的类型,并且不为nil
,可以使用as
操作符进行强制转换。
extension UIBezierPath {
class func bezierPathWithTriangle(length: Float,origin: CGPoint) -> UIBezierPath {
let squareRoot = Float(sqrt(3))
let altitude = (squareRoot * length) / 2
let myPath = UIBezierPath()
myPath.moveToPoint(orgin)
myPath.addLineToPoint(CGPoint(length,origin.x))
myPath.addLineToPoint(CGPoint(length / 2,altitude))
myPath.closePath()
return myPath
}
}
可以使用扩展增加属性(包括类属性或静态属性)。不过这些属性只能是通过计算得来,而不能进行存储。下面给CGRect
添加一个area
属性:
void (^completionBlock)(NSData *,NSError *) = ^(NSData *data,17)">NSError *error) {
/* ... */
}
在Swift 中对应为:
let completionBlock: (NSData,NSError) -> void = {
data,error in Swift的闭包和Objective-C中的Block是兼容的,可以在Swift中给Objective-C的方法传递闭包来代替Block对象。
闭包和Block对象有一点不同,里面的变量是可变的,也就是说与__block
修饰的变量行为相同。
对象比较
Swift中有两种对象比较的方式。第一种是相等(==
)(equality),用来比较两个对象的内容是否相同。第二种是恒等(===
)(identity),比较两个变量或者常量是否引用同一个对象。