swift 类型转换笔记
AnyObject
为了便于理解,你可以认为AnyObject是一种“type”(实际上并不是type),就像Double ,Array等,AnyObject主要用于兼容现有的Objective-C API和iOS代码,swift不能用AnyObject构建自己的数据结构,swift是强类型语言,并有类型推断的特性。
什么是AnyObject?在哪会看到AnyObject?
AnyObject的意思是指向一个对象的指针,也就是一个对象的实例,但你不知道它是什么class,所以它是指向未知类的指针
有时它会是某个类的属性如:
var destinationViewController: AnyObject
var toolbarItems: [AnyObject]
也有可能出现在方法的参数中:
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject)
func addConstraints(constraints: [AnyObject])
也可以作为返回值返回:
class func buttonWithType(buttonType: UIButtonType) -> AnyObject
怎么使用AnyObject?
为了使用它,我们把它转换成一种我们知道的类型
我们新建一个我们已知类型的变量,“变量 = AnyObject 转换后的东西“
我们可以使用 as 关键词进行强制转换,例如:
var destinationViewController: AnyObject
let calcVC = destinationViewController as CalculatorViewController 如果destinationViewController不是CalculatorViewController或者它的子类,程序将会crash
如果想防止crash,我们可以使用
if let with as?
if let calcVC = destinationViewController as? CalculatorViewController {
...
}
as? 返回一个可选类型(如果destinationViewController不是CalculatorViewController类型,calcVC = nil)
也可以在之前判断是不是CalculatorViewController类型:
if destinationViewController is CalculatorViewController {
...
}
通常我们更多的使用as?
Array中的AnyObject
vat toolbarItems: [AnyObject]
for item in toolbarItems { //item的类型是AnyObject
if let toolbarItem = item as? UIBatButtonItem {
//toolbarItem的类型是UIBatButtonItem
}
}
或者
for toolbarItem in toolbarItems as [UIBarButtonItem] {
//toolbarItem的类型是UIBatButtonItem
} 这里不能使用as? 因为toolbarItem不应该为nil,所以在使用这个方法是最好确定toolbarItems的类型是UIBarButtonItem
关于 as
由上可知,as可以用于将AnyObject转换为其他类型,同时as也可以用于其他任何类型的转换,但是对于两个非AnyObject对象,想要通过as转换,他们必须在同一条继承链上,并且只能向下转换。例如:
let vc : UIViewController = CalculatorViewController()
//vc被声明为UIViewController类型,但是创建了一个CalculatorViewController实例对象,这是是不能用vc调用CalculatorViewController的方法的
if let calcVC = vc as? CalculatorViewController {
//calcVC可以调用 CalculatorViewController的方法
}
Objective-C 兼容性
Bridging
Bridging意思是你可以对他们随意互换
NSString is bridged to String
NSArray is bridged to Array < AnyObjecy>
NSDictionary is breidged to Dictionary < NSObject, AnyObjecy>
Int, Float, Double, Bool are all bridged to NSNumber,在需要传入NSNumber时可以随意使用Int,Float等,但反过来不行,需要使用NSNumber的intValue, floatValued等方法
Int, Float, Double, Bool are all bridged to c语言的 int,float,double,bool
如果需要确定的类型,可以使用as进行转换(不需要使用as?)。例如:
let length = (aString as NSString).length //length是NSString的方法
(anArray as NSArray).componentsJoinedByString(NSString)
//componentsJoinedByString是NSArray的方法
这里我们可能会对NSDictionary有点疑问,它只接受NSObject作为key,我们知道swift中String,Array等都不是对象,而是结构,但因为他们bridged to NSObject的子类(NSString, NSArray)等,所以它们也是可以作为NSDictionary的key使用的。
总结 as的使用场景
- 对AnyObject进行转换
- 将父类对象转换为子类对象
- 对于具有bridge关系的对象进行相互转换
使用初始化方法实现类型转换
let d: Double = 37.5
let f: Float = 37.5
let x = Int(d)
let xd = Double(x)
let cgf = CGFloat(d)
let a = Array("abc") // a = ["a", "b", "c"]
let s = String(["a", "b", "c"]) // s = "abc"
let s = String(52) //不能是float
let s = "\(37.5)"
var f = 123.32342342
var s = String(format: "%.2f", f) //123.32,保留2位小数
let i = 255
let s:String = String(format: "%x", i) //ff, 转换成十六进制
let i = 255
let s:String = String(format: "%06x", i) //0000ff, 不足六位前面补0
let s = "32.5"
let d = Double(s)
let fd = (NumberFormatter().number(from: s)?.doubleValue)!
另外提一下AnyObject和Any的区别
AnyObject只能代表class类型,不能处理纯swift的结构等类型。
Any可以处理结构等所有类型。