2018-02-06 17:14:03 ZY_FlyWay 阅读数 2101
  • iOS从初级到精通就业 Objective-C

    C语言基础入门,面向初级,毫无编程经验的学生群体,通过学习能够掌握C语言的基本语法,编程的基本概念,培养自己的编程思维!OC语言详解,掌握OC核心内容(面向对象、内存管理,类的扩展,KVC和KVO,闭包和常见的Foundation类库的使用方法等,为后续学习iOS SDK打好基础。

    10123 人正在学习 去看看 栾斌

 我们都知道KVC 是OC  NSobject特有的,之前在Swift4.0之前,继承NSobject的对象,可用动态的拿到字典调用KVC给模型赋值。只是比较省事的操作,有没有定义属性,只要从写UndefinedKey这个属性即可。

 还是用代码演示比如下面一个对象,从字典赋值

//
//  UserAccount.swift
//  WeiBo
//
//  Created by 张宇 on 2018/2/6.
//  Copyright © 2018年 张宇. All rights reserved.
//

//
//  用户账号Model
//

import UIKit

class UserAccount: NSObject {
    
    //MARK : 存储属性
    var  access_token:String = ""
    var  expires_in:TimeInterval = 0.0
    var  uid:String?
    
    init(dict:[String:Any]){
        super.init()
        setValuesForKeys(dict)
    }
    
    override func setValue(_ value: Any?, forUndefinedKey key: String) {
        
    }
    
    override var description: String{
        return  dictionaryWithValues(forKeys: ["access_token","expires_in","uid"]).description
    }
}

3.0这样写肯定是没有错误的,但是4.0的时候你就会发现一个问题forUndefinedKey这个方法每次都会调用,然后就崩溃了。


猜测原因:这是因为KVC是OC 的方法,OC方法和属性都需要运行时写到类对象中,swift 利用KVC设置属性需要运行时机制,swift4.0以前,编译器默认帮我们做了在对象声明前加上了@objc,4.0需要手动加上。


  //MARK : 存储属性
    @objc var  access_token:String = ""
    @objc var  expires_in:TimeInterval = 0.0
    @objc var  uid:String?

   这样就不会报错了。



2018-04-20 22:05:43 ZhengYanFeng1989 阅读数 295
  • iOS从初级到精通就业 Objective-C

    C语言基础入门,面向初级,毫无编程经验的学生群体,通过学习能够掌握C语言的基本语法,编程的基本概念,培养自己的编程思维!OC语言详解,掌握OC核心内容(面向对象、内存管理,类的扩展,KVC和KVO,闭包和常见的Foundation类库的使用方法等,为后续学习iOS SDK打好基础。

    10123 人正在学习 去看看 栾斌
  1. swift 4.0   kvc 赋值失败问题  需要在模型属性前加上 @objc ,以保证属性被添加到运行时方法列表
  2.   @objc var  access_token:String = ""  
  3.   @objc var  expires_in:TimeInterval = 0.0  
  4.   @objc var  uid:String?
2018-01-19 09:11:48 mn704058053 阅读数 662
  • iOS从初级到精通就业 Objective-C

    C语言基础入门,面向初级,毫无编程经验的学生群体,通过学习能够掌握C语言的基本语法,编程的基本概念,培养自己的编程思维!OC语言详解,掌握OC核心内容(面向对象、内存管理,类的扩展,KVC和KVO,闭包和常见的Foundation类库的使用方法等,为后续学习iOS SDK打好基础。

    10123 人正在学习 去看看 栾斌
 1.首先创建一个Person的类 继承 NSObject类

//
//  Person.swift
//  006-Swift中设置模型数据
//
//  Created by 庄壮勇 on 2018/1/10.
//  Copyright © 2018年 Personal. All rights reserved.
//

import UIKit

class Person: NSObject {
    var name: String?
}
2.创建一个DemoLabel 类 继承于 UILable类
//
//  DemoLabel.swift
//  006-Swift中设置模型数据
//
//  Created by 庄壮勇 on 2018/1/10.
//  Copyright © 2018年 Personal. All rights reserved.
//

import UIKit

class DemoLabel: UILabel {

    // 模型 -> 给视图设置模型,由视图自己根据模型的数据,决定显示内容
    var person: Person? {
        // *** 就是替代 OC 中重写 setter 方法
        // 区别: 再也不需要考虑 _成员变量 = 值
        // OC 中如果是copy属性,应该 _成员变量 = 值.copy;
        didSet{
            // 此时 name 属性已经有值,可以直接使用设置UI内容
            text = person?.name
        }
    }
}
3.ViewController
//
//  ViewController.swift
//  006-Swift中设置模型数据
//
//  Created by 庄壮勇 on 2018/1/10.
//  Copyright © 2018年 Personal. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let p = Person()
        p.name = "小花"
        let label = DemoLabel(frame: CGRect(x: 20, y: 40, width: 100, height: 40))
        view.addSubview(label)
       
        // 将模型设置给label
        label.person = p
    }
}

2016-12-26 22:20:41 feng2qing 阅读数 1958
  • iOS从初级到精通就业 Objective-C

    C语言基础入门,面向初级,毫无编程经验的学生群体,通过学习能够掌握C语言的基本语法,编程的基本概念,培养自己的编程思维!OC语言详解,掌握OC核心内容(面向对象、内存管理,类的扩展,KVC和KVO,闭包和常见的Foundation类库的使用方法等,为后续学习iOS SDK打好基础。

    10123 人正在学习 去看看 栾斌

0.创建一个类:Person.swift

//name属性是可选的,在需要的时候创建
//在手机开发中,内存非常宝贵,实际运行中很多属性不一定需要分配空间
var name: String?

1.重写构造函数,用字典为本类设置初始值

init(dict: [String: AnyObject]) {

    super.init()
    //使用 self 的方法 'setValuesForKeys' 之前,应该调用 super.initt(),否则会奔溃:Use of 'self' in method call 'setValuesForKeys' before super.init initializes self
    //KVC方法是 OC 的方法,在运行的时候给对象发送消息
    //执行'setValuesForKeys',首先要求对象已经实例化完成
    setValuesForKeys(dict)
}

1.1然在控制器中传值调用

let p = Student(dict: ["name": "小明" as AnyObject])
print(p.name)
//打印输出: Optional("小明")

2.在Person.swift中继续追加一个属性

//给基本类型属性初始化
//如果这样写:
//var age: Int?
//会抛出以下异常:
//Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<******> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key age.'
// - 意思是KVC会无法找到age的KEY,因为Int是一个基本数据类型的结构体
//所以要这么写,赋初始值    
var age: Int = 0

2.1去控制器中传值调用

let p = Student(dict: ["name": "小明" as AnyObject,"age": 18 as AnyObject])
print("\(p.name) \(p.age)")
//打印输出: Optional("小明") 18

3.试图在Person.swift添加一个私有的属性

//private var title: String?
//直接报异常:Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<****** > setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key title.
// - 如果是private属性,使用KVC设置的时候,程序会直接崩溃
// - Swift中被Private修饰的属性或方法,彻底禁止外部访问,OC中私有属性或者方法可以通过runtime访问到,所以此时无法使用private修饰
var title: String?

3.1在控制器中打印输出

let p = Student(dict: ["name": "小明" as AnyObject,"age": 18 as AnyObject,"title": "北京" as AnyObject])
print("\(p.name) \(p.age) \(p.title)")
//打印输出: Optional("小明") 18 Optional("北京")

总结:

1. 定义属性的时候,如果是对象,通常都是可选的(类后面加’?’)

- 在需要的时候创建

- 避免写构造函数,可以简化代码

2. 如果是基本数据类型,不能设置为可选的,而且要设置初始值,否则KVC崩溃

3. 若果需要使用KVC设置属性,属性不能是private的

4. 使用KVC方法之前,应该调用 super.init 保证对象实例化完成

2019-01-23 11:29:22 qq_28091923 阅读数 296
  • iOS从初级到精通就业 Objective-C

    C语言基础入门,面向初级,毫无编程经验的学生群体,通过学习能够掌握C语言的基本语法,编程的基本概念,培养自己的编程思维!OC语言详解,掌握OC核心内容(面向对象、内存管理,类的扩展,KVC和KVO,闭包和常见的Foundation类库的使用方法等,为后续学习iOS SDK打好基础。

    10123 人正在学习 去看看 栾斌

在Swift中使用KVC分为3中情况:
1、在swift3.0之前,类必须要继承自NSObject,因为KVC是OC的东西
2、在Swift4.0之后,类必须要继承自NSObject,同时还需要在属性前面加上@objc
在Swift4.0之前,编译器会默认帮我们在对象属性前面加上@objc
在Swift里,有一种间接访问类属性的方法,叫做#keyPath
class Person : NSObject {
@objc var name:String = “”
init(dict:[String:Any]){
super.init()
setValuesForKeys(dict)
}
}
let p1 = Person(dict: [“name”:“lichangan”])
let name = p1.value(forKeyPath: #keyPath(Person.name))
print(name) //lichangan
p1.setValue(“shuaige”, forKeyPath: #keyPath(Person.name))
print(p1.name) //shuaige

        这就是Cocoa中的KVC机制,在Objective-C中它可以很好的工作,但移植到Swift之后,它的不足就显现出来了:
        value(forKeyPath:)方法返回的类型是Any?,这样我们就失去了类型信息,错误的赋值会直接导致运行时错误;
        只有NSObject的派生类才支持这种访问机制
 
    (3)Swift 4中设计了更智能的KeyPath
 
     class Person {
         var name:String = ""
         init(name:String){
            self.name = name;
         }
     }
 
     let p2 = Person(name:"lichangan")
     let nameKeyPath = \Person.name
     let name = p2[keyPath:nameKeyPath]
     print(name) //lichangan
     p2[keyPath:nameKeyPath] = "shuaige"
     print(p2.name) //shuaigei
 
    \Person.name 就是Swift4中新的key path用法,他是一个独立的类型,带有类型的信息。
    因此,编译器会发现错误类型的赋值,因此不会把这个错误延迟到运行时
 
    除了类型安全之外,新的KeyPath不需要继承自NSObject,也不需要使用@obj修饰属性,同时struct也可以使用新的KeyPath

不同之处

在 Swift 中处理 KVC和 Objective-C 中还是有些细微的差别。比如,Objective-C 中所有的类都继承自 NSObject,而 Swift 中却不是,所以我们在 Swift 中需要显式的声明继承自 NSObject。

可为什么要继承自 NSObject 呢?我们在苹果官方的 KVC 文档中找到了答案。其实 KVC 机制是由一个协议 NSKeyValueCoding 定义的。NSObject 帮我们实现了这个协议,所以 KVC 核心的逻辑都在 NSObject 中,我们继承 NSObject 才能让我们的类获得 KVC 的能力。(理论上说,如果你遵循 NSKeyValueCoding 协议的接口,其实也可以自己实现 KVC 的细节,完全行得通。但在实践上,这么做就不太值得了,太费时间了~)。

另外,因为 Swift 中的 Optional 机制,所以 valueForKey 方法返回的是一个 Optional 值,我们还需要对返回值做一次解包处理,才能得到实际的属性值。

第十三章 KVC和KVO

阅读数 301

objc.io KVC KVO 思维导图整理

博文 来自: u010801085

IOS开发-10.KVC

阅读数 383

2016.01.22 KVC&KVO

阅读数 0

没有更多推荐了,返回首页