Swift中的对象
构造函数
class Person: NSObject {
// 如果类中有必选属性(一定得有值),必须要在初始化方法里面去给其分配空间设置初始值
var name: String
var age: Int
// 父类 (NSObject)已经存在 init 方法,子类需要执行自己的逻辑,就重写这个方法,使用 `override`
// override: 重写
/**
构造函数:分配空间,初始化对象,给对象身上的属性赋值
Swift 中的构造函数没有 func
*/
override init() {
// 必须先初始化子类的必选属性,再初始化父类
name = "老王"
age = 18
// 在 Xcode 7 beta 5 之后,可以使用写 super.init() ,但是建议大家写上,调用层次更加明确
super.init()
}
}
子类的构造函数
class Student: Person {
// 学号 ,因为必选属性要在对象一初始化出来就必须保证有值,所以必须在init 方法中设置值
var no: String
override init() {
// 先初始化子类的`必选属性`,再调用 `super.init` 初始化父类
no = "008"
super.init()
}
重载构造函数
/**
重载:方法名相同,参数的个数,类型,参数名不同
构造函数
// 如果重载了构造函数,并没有重写默认的构造函数,默认构造函数就不再提供
*/
init(name: String, age: Int) {
self.name = name
self.age = age
super.init()
}
子类的重载构造函数
// 学号 ,因为必选属性要在对象一初始化出来就必须保证有值,所以必须在init 方法中设置值
var no: String
init(name: String, age: Int, no: String) {
self.no = no
super.init(name: name, age: age)
}
KVC构造函数
class Person: NSObject {
var name: String?
// OC 中基本数据类型 比如 int ,会有一个默认值,为0
// 在 Swift 中,KVC初始化的时候,如果 age 为基本数据类型,并且为可选值的话,kvc 是找不到这个值
var age: Int = 0
// KVC构造函数:是系统在运行时动态向`对象`发送 `setValue:forKey` 这个消息设置值
init(dict: [String: AnyObject]) {
// 调用 super.init 才代表对象创建完成
super.init()
// 传入字典,其方法内部会遍历字典调用 setValue:forKey这个方法
setValuesForKeysWithDictionary(dict)
}
// override func setValue(value: AnyObject?, forKey key: String) {
// // 这一句代码是父类帮我们设置值
// /**
// - 找与 key 名字相同的属性
// - 如果是基本数据类型可选类型 --> 是找不到这个错
// - 如果找到,会判断这个属性是否初始化过
// - 如果没有初始化过,系统会初始化这个属性,并设置值
// - 有初始化过的,就直接设置值
// */
// super.setValue(value, forKey: key)
// print("key=\(key),value=\(value)")
// }
//
// 在遍历字典调用 setValue:forKey 的方法的,如果没有找到字典里面对应的值,会调用这个,系统默认这个方法,抛出一个异常
override func setValue(value: AnyObject?, forUndefinedKey key: String) {
print(key)
}
便利构造函数
class Person: NSObject {
var name: String?
// OC 中基本数据类型 比如 int ,会有一个默认值,为0
// 在 Swift 中,KVC初始化的时候,如果 age 为基本数据类型,并且为可选值的话,kvc 是找不到这个值
var age: Int = 0
/** 便利构造函数
- 可以返回 nil (不一定能够初始化出来对象)
- 在自己内部调用当前类的其他指定构造函数初始化
- 只有便利构造函数才能调用自己身上的其他指定构造函数
- 可以根据不同情况判断是否初始化对象
*/
// 如果别人在初始化我们这个对象的时候,传入年龄大于150的话,就初始化不成功(返回一个 nil )
convenience init?(name: String, age: Int) {
if age > 150 {
return nil
}
// 在这儿初始化
self.init(dict: ["name": name, "age": age])
}
// KVC构造函数:是系统在运行时动态向`对象`发送 `setValue:forKey` 这个消息设置值
init(dict: [String: AnyObject]) {
// 调用 super.init 才代表对象创建完成
super.init()
// 传入字典,其方法内部会遍历字典调用 setValue:forKey这个方法
setValuesForKeysWithDictionary(dict)
}
// override func setValue(value: AnyObject?, forKey key: String) {
// // 这一句代码是父类帮我们设置值
// /**
// - 找与 key 名字相同的属性
// - 如果是基本数据类型可选类型 --> 是找不到这个错
// - 如果找到,会判断这个属性是否初始化过
// - 如果没有初始化过,系统会初始化这个属性,并设置值
// - 有初始化过的,就直接设置值
// */
// super.setValue(value, forKey: key)
// print("key=\(key),value=\(value)")
// }
//
// 在遍历字典调用 setValue:forKey 的方法的,如果没有找到字典里面对应的值,会调用这个,系统默认这个方法,抛出一个异常
override func setValue(value: AnyObject?, forUndefinedKey key: String) {
print(key)
}
}
子类的便利构造函数
class Student: Person {
var no: String?
// 便利构造函数只能继承不能重写。
convenience init?(name: String, age: Int, no: String) {
// 只能使用 self 去调用其他构造函数
self.init(name: name, age: age)
self.no = no
}
}
懒加载
// 懒加载的简单写法
lazy var person1: Person = Person()
// 懒加载的完整写法
/**
懒加载的就是执行一个闭包,执行闭包,获取到闭包的返回值,把返回值保存到使用 var 定义的变量
下次再使用的时候,不会执行后面的闭包,直接返回 person2
lazy:标识这个属性是懒加载
*/
lazy var person2: Person = {
print("我要初始化了")
let p = Person()
p.name = "老王"
p.age = 19
return p
}()
// 以下代码了解
let pFunc = { () -> Person in
print("我要初始化了")
let p = Person()
p.name = "老王"
p.age = 19
return p
}
lazy var person3: Person = self.pFunc()
getOnly 的属性
// 在 Swift 属性的 get 方法与 set 方法我们基本上不关注
// 了解一下
var _name: String?
// 这种属性,也叫存储型属性
var name: String?
var age: Int = 0
// 只读属性
// getOnly 属性 --> 在 Swift 中也叫计算型属性
var title: String? {
get {
// 可以写判断逻辑
return "Mr. \(name)"
}
}
// getOnly 写法
var title2: String {
return "Mr. \(name)"
}
网络访问
func loadData(){
// 初始化 url
// 考虑1:url是否真的能初始化出来
let url = NSURL(string: "http://www.baidu.com/")
NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, _, e) -> Void in
// 判断 error 是否有值
if e != nil {
print(e)
return
}
// 2. 考虑2: data 是否真的有值,没有值应该怎么办
// 位置移枚举在 Swift 是一个数组
// 3. 考虑3:能不能使用 强行try `try!`
// try! 告诉系统,我这个网络请求回来的数据一定可以可转成一个字典(后面的代码一定能够执行成功,不会抛错)
// try? 可能后面的代码会出现错误,如果出现错误,直接返回 nil
// try 可以捕获到代码执行的错误信息
// 判断 data 是否为空
guard let d = data else {
print("data为nil")
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(d, options: [])
print(result)
}catch{
// 如果上面的代码执行有问题,就会进入到这个地方
// 内部提供一个 error 供我们访问
print(error)
}
}).resume()
}
try try! try?
- try! 告诉系统,我这个网络请求回来的数据一定可以可转成一个字典(后面的代码一定能够执行成功,不会抛错)
- try 默认的.可以捕获到代码执行的错误信息
- try? 可能后面的代码会出现错误,如果出现错误,直接返回 nil