美文网首页
从OC到Swift(一)

从OC到Swift(一)

作者: TheEnded | 来源:发表于2020-02-23 11:26 被阅读0次

    开篇

    在简单的学习了swift语法之后,开始在项目里使用。很多东西都是别人铺好路,自己只是套用写UI而已。这里先简单过渡一下OC-Swift,后续再深入研究Swift相关知识。

    Swift与OC如何互相调用

    大部分项目应该都是要从OC过渡到Swift,这就避免不了混编,这里涉及到两个桥接头文件:

    1. Swift调用OC {targetName}-Bridging-Header.h

    作用:Swift可调用OC,在此文件中import OC的头文件

    在OC工程中创建swift文件时会有此提示,点击create Xcode会帮我们生产此文件。
    image.png
    并且在Targets-->Build Settings-->Swift Compiler - General-->Objective-C Bridging Header有配置路径。如果工程里没有此文件,我们可以手动创建,并且在这里配置一下,不过注意的是文件名字必须为上述格式{targetName}-Bridging-Header.h
    image.png
    2. OC调用Swift 一般为{targetName}-swift.h

    在上面图中我们看到Objective-C Generated Interface Header Name 这里也有一个配置的文件路径,这里就是让OC可与调用Swift。需要调用swift的地方,import这个文件就可以。
    名字为什们说一般为{targetName}-swift.h呢?当targetName中存在-这种情况,需要变_。 例如targetNameOC-Swift,这个头文件的名字应该是OC_Swift-Swift.h。这个文件内是swift编译生成的对应OC代码。
    这个文件在工程内不能直接看到,编译后,可以通过Command+单击该文件名,就会看到具体生成的代码。

    需要注意的是:
    • 在OC里如果想要调用Swift,需要在被访问的类,属性,方法前面加上@objc,并且如果是类,需要继承NSObject,否则编译也会报错。
      @objc class TestSwiftClass: NSObject { }
    • 这就又有问题了,如果一个类特别复杂都需要暴露给OC,那不是得写好多@objc?这时候可以使用@objcMembers, 这样类、类中的所有属性、方法都暴露给OC可以直接调用。
      @objcMembers class Car: NSObject { }
    • 我们还可以给swift属性、方法重新定义供OC使用的名字
    @objc(realName)
    var name: String; 
    @objc(ocRun)
    func run() {
    }
    

    以上整体下来示例:

    //swift中写法
    @objcMembers class TestSwiftClass: NSObject {
        @objc(realName)
        var name: String;
        var age: Int;
        init(name:String, age:Int) {
            self.name = name
            self.age = age
        }
        @objc(ocRun)
        func run() {
            
        }
    }
    
    //OC中调用
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        TestSwiftClass *obj = [[TestSwiftClass alloc]initWithName:@"zhangsan" age:12];
        obj.age = 11;
        obj.realName = @"ZhangSan";
        [obj ocRun];
    }
    
    • 我们上面会发现swif中定义的init方法init(name:String, age:Int),而OC里面调用还是我们熟悉的样子TestSwiftClass *obj = [[TestSwiftClass alloc]initWithName:@"zhangsan" age:12];
      而且OC里面的方法 - (instancetype)initWithTitle:(NSString *)title;到Swift中调用的时候是let obj = TestOCClass(title: "title")
      这里是xcode帮我做了优化,生成对应风格的代码。
    这里有个坑,就是你可能会发现在swift中无法调用一些OC的单例创建方法,比如 + (instancetype)manager, 或者+(instancetype)shareManager。后来发现需要定义一些标准名字比如default singleton shared 。不过这个问题应该在只存在某几个版本的Xcode中,目前发现Xcode11.3没有这个问题

    以上大概就已经做好混编的基础了。

    Selector的使用

    在OC里面我们经常使用@selector(name),在swift里面只是把@替换#,例:#selector(name)

    • 注意的是,必须是被@objcMembers或@objc修饰的方法才可以定义选择器。
      为什么呢?我们可以想一下@selector(name)是依赖OC的runtime,纯swift是没有runtime的,所以既然要使用方法选择器,说明需要用到runtime,所以需要通过关键字桥接到OC。当然在swift里面也可以调用perform(#selector(name))

    String的区别

    我们发现swift中的String在OC中会自动转换为NSString。但是Swift中的String的用法确与OC相差很大。在系统学习之前,我两个月都没用明白(但是不能承认自己笨。嗯!咳)。
    关于字符串拼接之类的就不多说了,主要说一下关于String的Index。
    String的下标(Index)并不是int类型,而是String.Index,Index是个结构体


    image.png

    虽然他不是整形,但是他一样代表着位置。关于String类型的一些方法,.startIndex/.endIndex!,例:name.startIndex/name.endIndex代表是起始位置(第一个字符的位置)/最后位置(最后一个字符的下一位)
    关于String的一些插入删除方法:

    //插入
    var str = "a-b"
    // 插入单个字符,最后一个位置插入‘-’,结果:a-b-
    str.insert("-", at: str.endIndex)
    // 插入字符串使用contentsOf:末尾插入c-d,结果:a-b-c-d
    str.insert(contentsOf: "c-d", at: str.endIndex)
    // after:str.startIndex,在第一个字符的后一位,结果:a666-b-c-d
    str.insert(contentsOf: "666", at: str.index(after: str.startIndex))
    // before:str.endIndex,在末尾的前一位,也就是最后一个字符的位置插入,从插入位置起,原字符都顺位后移,结果:a666-b-c-888d
    str.insert(contentsOf: "888", at: str.index(before: str.endIndex))
    // offsetBy:可以指定偏移量,从开始向后偏移3,也就是第三个6的位置,插入后,原字符顺位后移,结果  a66hello6-b-c-888d
    str.insert(contentsOf: "hello", at: str.index(str.startIndex, offsetBy: 3))
    
    //删除
    //删除第一个'-' 结果:a66hello6b-c-888d
    str.remove(at: str.firstIndex(of: "-")!)
    //删除所有,符合闭包条件的所有值。结果ahellob-c-888d
    str.removeAll { $0 == "6" }
    

    还有其他的关于range的方法,就不在这罗列了,明白了上面这些关于String.Index的使用,其他的基本一样了。

    Substring

    String可以通过下标、 prefix、 suffix等截取子串,但是子串类型不是String,而是Substring。String本身就是个结构体,不能被继承。Substring也就不是什么子类之类的。他一样也是个结构体。

    • Substring 是字符串的一部分,和父字符串共享同一块内存空间,并且记录了自己的开始和结束位置。
    • String 和 Substring 都声明实现了 StringProtocol。StringProtocol 包含了一个字符串的基本属性和功能。
    • Substring发生修改 或者 转为String时,会分配新的内存存储字符串数据
      具体细节,大家自行Google吧。

    相关文章

      网友评论

          本文标题:从OC到Swift(一)

          本文链接:https://www.haomeiwen.com/subject/cioqqhtx.html