プロトコルdynamicKVCKVO関連オブジェクトリソース名管理
5621 ワード
classにしか継承できないプロトコル
@objc
修飾された合意は、暴露も可能OC
遵守実現 protocol Runnable : AnyObject {}
protocol Runnable : class {}
@objc protocol Runnable: {}
オプションのプロトコル
@objc
オプションプロトコルを定義し、このプロトコルはclass
遵守@objc protocol Runnable {
func run1()
@objc optional func run2()//
func run3()
}
class HomeViewController: UIViewController, Runnable {
func run1() {
}
func run3() {
}
}
dynamic
@objc dynamic
修飾されたコンテンツにダイナミック性があり、例えば呼び出し方法が進むruntime
その流れclass Dog: NSObject {
@objc dynamic func test1(){}//runTime
func test2() { }//
}
KVC \ KVO
Swift
サポートKVC\KVO
の条件NSObject
@objc dynamic
対応する属性を修飾class Observer: NSObject {
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("observeValue",change?[.oldKey] ?? (Any).self)
print("observeValue",change?[.newKey] ?? (Any).self)
}
}
class Person: NSObject {
@objc dynamic var age: String = "0"
var observer: Observer = Observer()
override init() {
super.init()
self.addObserver(observer, forKeyPath: "age", options: [.new,.old], context: nil)
}
deinit {
self.removeObserver(observer, forKeyPath: "age")
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
let p = Person()
p.age = "20"
p.age = "30"
p.setValue("25", forKey: "age")
}
}
//
observeValue 0
observeValue 20
observeValue 20
observeValue 30
observeValue 30
observeValue 25
block方式のKVO
class Person: NSObject {
@objc dynamic var age: Int = 0
var observation: NSKeyValueObservation?
override init() {
super.init()
observation = observe(\Person.age, options: .new, changeHandler: { (_, change) in
print(change.newValue as Any)
})
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
let p = Person()
p.age = 10
}
}
関連オブジェクト(Associated Object)
Swift
中、class
依然として関連オブジェクトが使用可能extension
ストレージ属性を追加できないextension
はclass
記憶属性を増やす効果class Person { }
extension Person {
private static var AGE_KEY: Void?
var age: Int {// ,
get {
(objc_getAssociatedObject(self, &Self.AGE_KEY) as? Int) ?? 0
}
set {
objc_setAssociatedObject(self, &Self.AGE_KEY, newValue, .OBJC_ASSOCIATION_ASSIGN)
}
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
let p = Person()
print(p.age)//0
p.age = 10;
print(p.age)//10
}
}
リソース名管理
let img = UIImage(named: "logo")
let btn = UIButton(type: .custom)
btn.setTitle(" ", for: .normal)
performSegue(withIdentifier: "login_main", sender: self)
Android
資源名管理方式enum R {
enum string: String {
case add = " "
}
enum image: String {
case logo
}
enum segue: String {
case login_main
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
let img = UIImage(named: R.image.logo.rawValue)
let btn = UIButton(type: .custom)
btn.setTitle(R.string.add.rawValue, for: .normal)
performSegue(withIdentifier: R.segue.login_main.rawValue, sender: self)
}
}
enum R {
enum string: String {
case add = " "
}
enum image: String {
case logo
}
enum segue: String {
case login_main
}
}
extension UIImage {
convenience init?(_ name: R.image) {
self.init(named: name.rawValue)
}
}
extension UIViewController {
func performSegue(withIdentifier identifier: R.segue, sender: Any?){
performSegue(withIdentifier: identifier.rawValue, sender: sender)
}
}
extension UIButton {
func setTitle(_ title: R.string, for state: UIControl.State) {
setTitle(title.rawValue, for: state)
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
let img = UIImage.init(R.image.logo)
let btn = UIButton(type: .custom)
btn.setTitle(R.string.add, for: .normal)
performSegue(withIdentifier: R.segue.login_main, sender: self)
}
}
enum R {
enum image {
static var logo = UIImage(named: "logo")
}
enum font {
static func arial(_ size: CGFloat) -> UIFont? {
UIFont(name: "Arial", size: size)
}
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
let img = R.image.logo
let font = R.font.arial(14)
}
}