swift语法(三)

17.面向对象

懒加载

懒加载的格式如下 :
------------  ViewController.swift ------------
class ViewController: UIViewController {
   
    /**
    ` ` 加载 , 本质上是一个闭包
    第一次访问属性时 , 会执行后面的代码 , 将闭包的 ` 结果 ` 保存在 person 属性中
    下次再访问 , 就不会再执行闭包 !
   
    如果没有 lazy, 会在 initWithCoder 方法中被调用 , ` 二进制 ` storyboard 被还原成视图控制器对象之后 , 就会被调用
    提示 : 在开始的时候 , 可以先尝试记忆语法 !
    */
   
    // 1. 懒加载的简单写法
    lazy  var demoPerson2: HMPerson = HMPerson()
   
   
    // 2. 懒加载写法
    lazy  var person: HMPerson = {
        print( " 懒加载 ")
       
        return  HMPerson()
        }()
   
    // -- 以下代码仅供参考 , 演示闭包 --
    // 1. 定义闭包
    let personFunc = { () -> ( HMPerson) in
        print( " 懒加载测试 ...")
       
        return  HMPerson()
    }
   
    // 2. 测试懒加载
    lazy  var demoPerson: HMPerson = self. personFunc()
   
   
    // 视图加载完成
    override  func viewDidLoad() {
        super. viewDidLoad()
       
        print( demoPerson2)
       
    }
   
    // 屏幕的触摸事件
    override  func touchesBegan(touches: Set< UITouch>, withEvent event: UIEvent?) {
        print( demoPerson2)
}
}
 

18.getter 方法 和 lazy 懒加载的对比

------------  HMPerson.swift ------------
 
class HMPerson: NSObject {
   
    // -- getter & setter 方法在 swift 中极少用 , 仅供参考
    // OC 中利用 getter 方法 , 编写懒加载 , swift 中提供了 lazy
   
    // 如果不希望暴露的方法或者属性 , 都需要用 private 保护起来 !
    private  var _name: String?
    var name: String? {
        get {
            // 返回 _ 成员变量   的值
            return  _name
        }
        set {
            // 使用 _ 成员变量   记录新的数值
            _name = newValue
        }
    }
   
    var name2: String// 完成的效果与上面一样
   
    // -- read only 属性 , 只写 getter 方法
    // swift , get only 属性 , 只写 getter 方法 , 可以进行多次赋值 , 同时也成为 ` 计算 ` 型属性
    var title: String? {
        get {
            return  "Mr " + ( name ?? "")
        }
    }
   
    /**
        只读属性的简写方法 - 如果属性的 ` 修饰 ` 方法 , 只提供 getter , 那么 get {} 可以省略
        每次调用的时候 , 都会执行 {} 中的代码 , ` 结果取决于其他属性或者原因 `
        1> 每次都要计算 , 浪费性能 - 如果计算量很小 , 可以使用
        2> 不需要开辟额外的空间
    */
    var title2: String? {
        return  "Mr 222" + ( name ?? ""// 特别注意 : getter 方法 , 只读属性 , 可以多次赋值
    }
   
   
    /**
        懒加载 - 第一次调用的时候 , 执行闭包 , 并且在 title3 中保存闭包执行结果
        再次调用 , 不再执行闭包 , 而是直接返回之前计算的结果 !
        1> 只需要计算一次
        2> 需要开辟单独的空间来保存计算结果
        3> 闭包的代码 , 再也不会被调用 !
        4> 如果计算量很大 , 需要提前准备
    */
    lazy  var title3: String? = {
        /**
            闭包 : 是一个提前准备好的代码 , 在需要的时候执行
            使用 : self. 用于闭包在执行时 , 准确的绑定对象
            注意 : 闭包中的 self. 是不能省略的 !
        */
        return  "Mr 333" + ( self. name ?? "")
    }()
}
 
------------  ViewController.swift ------------
override  func viewDidLoad() {
        super. viewDidLoad()
       
        let person = HMPerson()
       
        person. name = " 张三 "
       
        print(person. name) // getter & setter 方法   -> Optional(" 张三 ")
        print(person. title2) // getter 方法   (get only)  -> Optional("Mr 222 张三 ")
        print(person. title3) // lazy 懒加载   -> Optional("Mr 333 张三 ")
       
        print( "-----------")
       
        person. name = nil
        person. name = " 李四 "
       
        print(person. title2) // getter 方法   -> Optional("Mr 222 李四 ") 被修改
        print(person. title3) // lazy 懒加载   -> Optional("Mr 333 张三 ")  未修改 ( 即使清空 , 也不能修改 )
}
 
 
 

19.Xcode 7 网络访问

ATS 应用传输安全   官方文档描述如下 :
App Transport Security (ATS) lets an app add a declaration to its Info.plist file that specifies the domains with which it needs secure communication. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one. 

If you’re developing a new app, you should use HTTPS exclusively. If you have an existing app, you should use HTTPS as much as you can right now, and create a plan for migrating the rest of your app as soon as possible.
 

程序运行报错信息如下 :

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
 
设置强制访问 :
< key > NSAppTransportSecurity </ key >  
< dict >   
    <!--Include to allow all connections (DANGER)-->   
< key > NSAllowsArbitraryLoads </ key >       
    < true />  
</ dict >
 

OC 网络测试代码如下

------------  HMNetworkController.m ------------
- ( void)viewDidLoad {
    [ super  viewDidLoad];
   
    NSURL *url = [ NSURL  URLWithString: @"http://www.weather.com.cn/data/sk/101010100.html"];
   
    [[[ NSURLSession  sharedSession] dataTaskWithURL:url completionHandler:^( NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 反序列化
        id result = [ NSJSONSerialization  JSONObjectWithData:data options: 0  error: NULL];
        NSLog( @"%@", result);
    }] resume];
}
 
 

swift 中的 JSON 反序列化

JSON 序列化
    override  func viewDidLoad() {
        super. viewDidLoad()
       
        let url = NSURL(string: "http://www.weather.com.cn/data/sk/101010100.html")
        // `_` 表示忽略    session 默认超时时长 60s
        NSURLSession. sharedSession(). dataTaskWithURL(url!) { (data, _, _) -> Void  in
            /**
                JSON 是一个特殊格式的字符串
                反序列化 - `throws` 2.0 的语法 , 捕获异常
                注意点 : OC 中的安慰枚举的方式改为数组的方式设置 [ 1, 2]
                try! 程序员要负责 , 如果数据格式不正确 , 会崩毁 !
            */
            let result = tryNSJSONSerialization. JSONObjectWithData(data!, options: [ NSJSONReadingOptions.MutableContainers, NSJSONReadingOptions.MutableLeaves])
            print(result)
            }. resume()
        }
 



网络中的 do catch 语法
    override  func viewDidLoad() {
        super. viewDidLoad()
       
        let url = NSURL(string: "http://www.weather.com.cn/data/sk/101010100.html")
       
        NSURLSession. sharedSession(). dataTaskWithURL(url!) { (data, _, _) -> Void  in
           
            do {
                let result = try  NSJSONSerialization. JSONObjectWithData(data!, options: [])
                print(result)
            } catch {   // 如果反序列化失败 , 能够捕获到 JSON 失败的准确原因 , 而不会崩溃
                print(error)
            }
        }. resume()
}
 
// 正确信息返回
{
    weatherinfo =     {
        Radar = "JC_RADAR_AZ9010_JB";
        SD = "26%";
        WD = "\U4e1c\U5357\U98ce";
        WS = "2\U7ea7";
        WSE = 2;
        city = "\U5317\U4eac";
        cityid = 101010100;
        isRadar = 1;
        njd = "\U6682\U65e0\U5b9e\U51b5";
        qy = 1012;
        temp = 10;
        time = "10:25";
    };
}
 
 
// 模拟JSON 格式错误
    override  func viewDidLoad() {
        super. viewDidLoad()
       
        let url = NSURL(string: "http://www.weather.com.cn/data/sk/101010100.html")
       
        NSURLSession. sharedSession(). dataTaskWithURL(url!) { (data, _, _) -> Void  in
           
            // JSON 是一个特殊格式的字符串   | 格式不正确 , json 不是数组
            let jsonStr = "\"hello\", \"world\"]"
            let jsonData = jsonStr. dataUsingEncoding( NSUTF8StringEncoding)
           
            do {
                let result = try  NSJSONSerialization. JSONObjectWithData(jsonData!, options: [])
                print(result)
            } catch {   // 如果反序列化失败 , 能够捕获到 JSON 失败的准确原因 , 而不会崩溃
                print(error)
            }
        }. resume()
}
 
错误信息输出 程序没有奔溃 !
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
 
 

20.网络中的 guard else 语法

    override  func viewDidLoad() {
        super. viewDidLoad()
       
        let url = NSURL(string: "http://www.weather.com.cn/data/sk/101010100.html")
       
        NSURLSession. sharedSession(). dataTaskWithURL(url!) { (data, _, _) -> Void  in
            // JSON 格式错误测试
            let jsonStr = "\"heallo\", \"world\"]"
            let jsonData = jsonStr. dataUsingEncoding( NSUTF8StringEncoding)
           
            guard  let result = tryNSJSONSerialization. JSONObjectWithData(jsonData!, options: [ NSJSONReadingOptions.MutableContainers, NSJSONReadingOptions.MutableLeaves]) else {
                print( " 反序列化失败 ")
                return
            }
           
            print(result)
        }. resume()  // 但一定要记得开启
}
 
错误信息输出 程序没有奔溃 !
反序列化失败
 
补充:
17.懒加载—实际上是一个闭包: lazy关键字
懒加载的几种写法:
 1. lazy var person: Person = Person ()
2. lazy var person2: Person = {
       
let p = Person ()

       
// 设置 p 的属性
        // ...
       
       
return p
    }()
3. lazy var person3 = { () -> Person ? in
       
return Person ()
    }()
特点:在第一次调用时候,执行闭包,执行完成之后,会把值保存在前面的变量中,闭包代码永远都不会再次执行,
注意:懒加载的方法和OC的方法区别:
        1. 在第一次调用 person3 的时候,会执行闭包中的代码,然后将结果保存在 person3
        2. 一旦执行之后,闭包代码永远都不会再次执行!
        3. person3 负责存储对象,闭包只是执行并且返回结果
例子;
18.构造函数中的getter 和 setter 方法:(几乎不用)
private : swift中 默认都是全局共享的,如果不希望暴露的属性和方法 ,用private修饰,提示:对于变量和方法,尽量都使用private, Swift 中,如果使用 kvc 设置 private 属性,会崩溃
private var _name: String ? //属性
格式: var name: String ? {
get{
返回成员变量
return _name
}
set{
_name = newValue
使用成员变量记录数值,
newValue 就是设置过来的数值
}
}

19.只读属性:—计算型属性,本身不存储内容,通过计算获得结果,例子:
计算型属性可以简写:----直接return
例子: 计算型属性和懒加载有什么区别:
// 计算型属性可以简写 - 直接 return
    // 本身不存储内容,通过计算获得结果
    // 不需要为 title2 分配空间,每次临时计算
    // 消耗 CPU ,节省内存
    var title2: String {
       
return "Mr2222 " + ( name ?? "" )
    }

  懒加载 —存储型属性
    // 在第一次调用的时候,执行闭包,将计算结果保存在变量中
    // 需要为 title3 分配空间 - 存储型属性
    // 只计算一次,始终记录最初结果!
    // 节省 CPU ,消耗内存!在 tableView 中要少用计算型属性!
    lazy var title3: String = {
       
return "Mr333 " + ( self . name ?? "" )
    }()

didSet: 相当于OC中的set方法 // 模型
    var person: Person ? {
       
didSet {
           
// didSet 会在 person 被设置完成之后调用,此时 person 已经有值
            // didSet 中,不需要考虑 _ 成员变量 = value
            print ( person )
           
           
textLabel ?. text = person ?. name
           
detailTextLabel ?. text = person ?. phone
        }
    }




20.json的反序列化:
  let url = NSURL (string: "http://www.weather.com.cn/data/sk/101010100.html" )
       
       
NSURLSession . sharedSession (). dataTaskWithURL (url!) { (data, _ , _ ) -> Void in
           
           
// JSON 本质上是特殊格式的字符串
            let jsonString = "[\"hello\", \"world\"]"
           
let data = jsonString. dataUsingEncoding ( NSUTF8StringEncoding )
           
           
// 反序列化
            // options 是枚举类型的 复数, Swift 中使用数组表示
            // throw 抛出异常
            // 方法 1 try? - 如果 json 格式不正确,返回 nil
            // 方法使用的频率高!
            let json1 = try ? NSJSONSerialization . JSONObjectWithData (data!, options: [.AllowFragments, .MutableContainers])
           
print (json1)
           
           
// 方法 2 try! - 如果 json 格式不正确,直接崩溃
            // 实际开发不建议使用
            // let json2 = try! NSJSONSerialization.JSONObjectWithData(data!, options: [])
           
           
// print(json2)
           
           
// 方法 3 try
            // 能够捕获到错误信息,并且程序不回崩溃!
            do {
               
let json3 = try NSJSONSerialization . JSONObjectWithData (data!, options: [])
               
print (json3)
            }
catch {
               
print (error)
            }
           
        }.resume()
注意: 如果希望在程序中访问 OC 的对象,可以将 OC 的头文件放置在桥接头文件中


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值