JHHK

欢迎来到我的个人网站
行者常至 为者常成

18_02、OC到Swift(二)

目录

]

选择器的用法

//一、选择器的用法
func selectorUse() -> Void {
    /**
     选择器(Selector) n
     wift中依然可以使用选择器,使用#selector(name)定义一个选择器
     必须是被@objcMembers或@objc修饰的方法才可以定义选择器
     */
    
    @objcMembers class Person: NSObject {
        
        func test1(v1: Int) { print("test1: v1 is ",v1) }
        
        func test2(v1: Int, v2: Int) { print("test2(v1:v2:)") }
        
        func test2(_ v1: Double, _ v2: Double) { print("test2(_:_:)") }
        
        func run() {
            perform(#selector(test1))
            perform(#selector(test1(v1:)))
            perform(#selector(test1(v1:)),with: 5)
            
            perform(#selector(test2(v1:v2:)))
            perform(#selector(test2(_:_:)))
            perform(#selector(test2 as (Double, Double) -> Void))
        }
        
    }
    
    let person = Person()
    person.run()
    /**
     test1: v1 is  4295577213
     test1: v1 is  4295577213
     test1: v1 is  6932140607943212441
     test2(v1:v2:)
     test2(_:_:)
     test2(_:_:)
     */
}

string 的用法

//1、 空字符串
do{
    print("------1-------")
    //Swift的字符串类型String,跟OC的NSString,在API设计上还是有较大差异
    let emptyStr1 = ""
    let emptyStr2 = String()
    print("emptyStr1:\(emptyStr1)","emptyStr2:\(emptyStr2)",separator:"|")
}
//2、字符串获取
do{
    print("------3-----")
    let str = "123456"
    print(str.hasPrefix("123")) // true
    print(str.hasSuffix("456")) // true
    
    //str.startIndex 指向 0
    print(str[str.startIndex])//1
    
    //str.endIndex 指向 str.count
    //print(str[str.endIndex])//error 越界
    print(str[str.index(str.endIndex, offsetBy: -1)])//6
    
    
    let str2 = "22334455"
    print(str[str2.firstIndex(of: "4")!])   //5
    print(str[str2.lastIndex(of: "4")!])    //6
}
//3、字符串拼接
do{
    print("------2-----")
    var str: String = "1"
    
    // 拼接,jack_rose
    str.append("_2")
    print(str)//1_2
    
    // 重载运算符 +
    str = str + "_3"
    print(str)//1_2_3
    
    
    // 重载运算符 +=
    str += "_4"
    print(str)//1_2_3_4
    
    // \()插值
    str = "\(str)_5"
    print(str)//1_2_3_4_5
    
    
    print(str.count)//9
}
    //4、字符串插入删除
    do{
        print("--------4---------")
        var str = "1_2"
        
        // 1_2_
        str.insert("_", at: str.endIndex)
        
        
        // 1_2_3_4
        str.insert(contentsOf: "3_4", at: str.endIndex)
        
        
        // 1666_2_3_4
        str.insert(contentsOf: "666", at: str.index(after: str.startIndex))
        
        
        // 1666_2_3_8884
        str.insert(contentsOf: "888", at: str.index(before: str.endIndex))
        
        
        // 1666hello_2_3_8884
        str.insert(contentsOf: "hello", at: str.index(str.startIndex, offsetBy: 4))
        
        
        // 666hello_2_3_8884
        str.remove(at: str.firstIndex(of: "1")!)
        
        
        // hello_2_3_8884
        str.removeAll { $0 == "6" }
        
        
        // hello_2_3_4
        let range = str.index(str.endIndex, offsetBy: -4)..<str.index(before: str.endIndex)
        str.removeSubrange(range)
    }
    //5、String 与 Character
    do{
        print("-------5--------")
        
        for c in "jack" { // c是Character类型
            print(c)
        }
        
        let str = "jack"
        let c = str[str.startIndex]// c是Character类型
        print("c is ", c)
    }
    //6、substring
    do{
        print("------6-------")
        //String可以通过下标、 prefix、 suffix等截取子串,
        //子串类型不是String,而是Substring
        var str = "1_2_3_4_5"
        
        
        let substr1 = str.prefix(3)
        print(substr1)// 1_2
        
        
       
        let substr2 = str.suffix(3)
        print(substr2) // 4_5
        
        
       
        let range = str.startIndex..<str.index(str.startIndex, offsetBy: 3)
        let substr3 = str[range]
        print(substr3) // 1_2
        
        
        // 最初的String,
        print(substr3.base)// 1_2_3_4_5
        
        
        
        /**
         Substring和它的base,共享字符串数据
         Substring发生修改 或者 转为String时,会分配新的内存存储字符串数据
         str的修改,也不会影响substr值
         */
        
        // Substring -> String
        let str2 = String(substr3)
        print(str2) //1_2

        str = "hello"
        print(substr1)//1_2
        print(substr1.base)//1_2_3_4_5
    }
    //7、String相关的协议
    do{
        /**
         BidirectionalCollection 协议包含的部分内容
            startIndex 、 endIndex 属性、
            index 方法
            String、Array 都遵守了这个协议
         
         
         RangeReplaceableCollection 协议包含的部分内容
            append、insert、remove 方法
            String、Array 都遵守了这个协议
         
         Dictionary、Set 也有实现上述协议中声明的一些方法,只是并没有遵守上述协议
         */
    }
    //8、多行String
    do{
        print("------8-------")
        let str0 = """
        1
        "2"
        3
        '4'
        """
        print(str0)
        
        
        // 如果要显示3引号,至少转义1个引号
        let str1 = """
        Escaping the first quote \"""
        Escaping two quotes \"\""
        Escaping all three quotes \"\"\"
        """
        print(str1)
        
        // 以下2个字符串是等价的
        let str2_1 = "These are the same."
        let str2_2 = """
        These are the same.
        """
        print("str2_1:",str2_1)
        print("str2_2:",str2_2)
        
        
        // 缩进以结尾的3引号为对齐线
        let str3 = """
                1
            2       3
                4
            """
        print(str3)
    }
    //9、String 与 NSString
    do{
        print("-------9---------")
        /**
        String 与 NSString 之间可以随时随地桥接转换
        如果你觉得String的API过于复杂难用,可以考虑将String转为NSString
        */
        
        let str1: String = "jack"
        let str2: NSString = "rose"
        let str3 = str1 as NSString
        let str4 = str2 as String
        print(str4)//rose
        
        
        let str5 = str3.substring(with: NSRange(location: 0, length: 2))
        print(str5)// ja
        
        /**
         比较字符串内容是否等价
         String使用 == 运算符
         NSString使用isEqual方法,也可以使用 == 运算符(本质还是调用了isEqual方法)
         */
    }
}
Swift、OC桥接转换表
String NSString
String NSMutableString
Array NSArray
Array NSMutableArray
Dictionary NSDictionary
Dictionary NSMutableDictionary
Set NSSet
Set NSMutableSet

可选协议

//三、可选协议

//1、只能被class继承的协议
//被 @objc 修饰的协议,还可以暴露给OC去遵守实现
protocol LCRunnable181: AnyObject {}
protocol LCRunnable182: class {}
@objc protocol LCRunnable183 {}

//2、可选协议
//可以通过 @objc 定义可选协议,这种协议只能被 class 遵守
@objc protocol LCRunnable184 {
    func run1()
    @objc optional func run2()
    func run3()
}
func optionalProtocol() -> Void {
    class Dog: LCRunnable184 {
        func run3() { print("Dog run3") }
        //func run2() -> Void {print("Dog run2")}//可以不实现
        func run1() { print("Dog run1") }
    }
    
    let d = Dog()
    d.run1() // Dog run1
    d.run3() // Dog run3
}

dynamic

//四、dynamic
func dynamicUse() -> Void {
    //被 @objc dynamic 修饰的内容会具有动态性,比如调用方法会走runtime那一套流程
    class Dog: NSObject {
        @objc dynamic func test1() {}
        func test2() {}
    }
    
    let d = Dog()
    d.test1()//objc_msgsend会走消息发送机制
    d.test2()
}

kvc kvo

//五、 kvc kvo
func kvcKvoUse() -> Void {
    
    /**
     Swift 支持 KVC \ KVO 的条件
        属性所在的类、监听器最终继承自 NSObject
        用 @objc dynamic 修饰对应的属性
     */
    
    
    //1、kvc kvo
    do{
        print("--------1--------")
        
        class Observer: NSObject {
            override func observeValue(forKeyPath keyPath: String?,
                                       of object: Any?,
                                       change: [NSKeyValueChangeKey : Any]?,
                                       context: UnsafeMutableRawPointer?) {
                print("observeValue new ", change?[.newKey] as Any)
                print("observeValue old ", change?[.oldKey] as Any)
            }
        }
        
        class Person: NSObject {
            
            @objc dynamic var age: Int = 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")
            }
        }
        
        
        let p = Person()
        
        //observeValue new  Optional(20)
        //observeValue old  Optional(0)
        p.age = 20
        
        
        //observeValue new  Optional(25)
        //observeValue old  Optional(20)
        p.setValue(25, forKey: "age")
    }
    
    
    //2、block方式的KVO
    do{
        print("--------2--------")
        class Person: NSObject {
            
            @objc dynamic var age: Int = 0
            
            var observation: NSKeyValueObservation?
            
            override init() {
                super.init()
                
                observation = observe(\Person.age, options: [.new,.old]) {
                    (person, change) in
                    print("person :",person)
                    print("newValue :",change.newValue as Any)
                    print("oldValue :",change.oldValue as Any)
                }
            }
        }
        
        
        let p = Person()
        
        //person : <_TtCF20LCClientDemo_commond9kvcKvoUseFT_T_L0_6Person: 0x101806340>
        //newValue : Optional(20)
        //oldValue : Optional(0)
        p.age = 20
        
        
        //person : <_TtCF20LCClientDemo_commond9kvcKvoUseFT_T_L0_6Person: 0x101806340>
        //newValue : Optional(25)
        //oldValue : Optional(20)
        p.setValue(25, forKey: "age")
    }
}

关联对象(Associated Object)

//六、关联对象(Associated Object)
class LCPerson182 {}
extension LCPerson182 {
    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)
        }
    }
}
func associatedUse(){
    /**
     在Swift中,class依然可以使用关联对象
        默认情况,extension不可以增加存储属性
        借助关联对象,可以实现类似extension为class增加存储属性的效果
     */
    
    let p = LCPerson182()
    print(p.age) // 0
    
    
    p.age = 10
    print(p.age) // 10
}

资源名管理

//七、资源名管理
func sourceNameManager() -> Void {
    
    /**
     /// 资源管理方式 这种做法实际上是参考了Android的资源名管理方式
     enum R {
         enum button: String {
             case add = "添加"
             case del = "删除"
         }
         enum image: String {
             case logo
         }
         enum segue: String {
             case login_main
         }
     }
     */
    
    /**
     
     /// 创建一个imageView
     /// - Returns: void
     private func __createBtn() -> Void {
         let btn = UIButton(type: .custom)
         //btn.setTitle("添加", for: .normal)
         btn.setTitle(R.button.add.rawValue, for: .normal)
         btn.frame = CGRect.init(x: 20, y: 20, width: 100, height: 60)
         btn.backgroundColor = UIColor.green
         self.view.addSubview(btn)
     }
     

     
     /// 创建一个imageView
     /// - Returns: void
     private func __createImgView() -> Void {
         
         //let img = UIImage(named: "logo")
         let img = UIImage(named: R.image.logo.rawValue)
         
         let imageView = UIImageView.init(image: img)
         
         imageView.frame = CGRect.init(x: 20, y: 100,
                                       width: self.view.frame.size.width-40,
                                       height: 100)

         self.view.addSubview(imageView)
     }

     */
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.