大多数浏览器和
Developer App 均支持流媒体播放。
-
Swift 和 Objective-C 的互操作性
探索可以让您更轻松地编写能在 Swift 中流畅工作的 Objective-C API 的新功能,以及可以提供更出色的互操作性的 Swift 语言新功能。Apple 工程师还将探讨可提升 Swift 体验的 Apple SDK 增强功能。
资源
-
下载
Swift和Objective-C 互操作性
大家下午好 我是约旦·羅斯
哇 谢谢你们我还什么都没做
我是约旦·羅斯 过会儿道格·格雷戈尔也会加入我们 我们想要和你们分享一年来我们在 Swift和Objective-C语言的改进 特别是在互操作性方面的变化 因为Objective-C 和Swift的类库都相同 所以这很重要 在Xcode 7中我们更容易看到 这个映射是如何工作的 来到Objective-C的头文件 在顶部靠左的位置 选择显示关联项按钮 会跳出关联项菜单 其中一个是生成的接口 这会显示SWIFT的对于 这个头文件的映射
这和Xcode 6中用”调到定义 场景中的视图是完全一样的 但是现在你可以很容易的在对象中的 任意头文件中得到这个映射关系
今天我们将会讲到多种 在Swif 和Objective-C混编中 和在Objective-C中的 开发的新特性 我们将从一些Swif 和Objective-C混编 的基本特性开始重点 讨论新的错误处理特性和这种特性 跨语言工作原理 然后我们将会 讲在过去一年中关于 Objective-C的3个 主要改进包括“可空性注释” “轻量通用类型”和“种类型”
我们从Swift端开始 我们会看到将 Objective-C APIs 嵌入Swift有多容易 但是问题来了 什么时候把Swift暴露给 Objective-C代码
让我们复习一下规则
如果你有一个NSObject的子类 那么默认的它的方法和属性暴露 给Objective-C代码 在这个例子中我们有一个 我的控制器类是 UIViewController的 子类 那是NSObject的非直接子类 所以这个刷新方法将暴露给 Objective-C
然而如果你把这个方法标记为私有的 这意味着它仅在当前文件中可见 所以在这里默认情况下 Swift不会将这个方法暴露 给Objective-C
另外如果你仅仅使用 如果使用一些Swift专用的特性 就没有办法把这个方法 暴露给Objective-C Swift甚至试都不会试
最后如果不是NSObject的子类 仅粗略的符合 Objective-C协议 那么你必须格外注意 你的方法必须完全的满足协议要求 在Xcode 7你会得到这样的告警 在这里 “页面视图开始加载” 不是objc 它不能满足 “UI web视图代理协议”的要求
这涵盖了默认值 你把这些默认行为 变成这样时会发生什么? 让我们回到具有刷新 方法的我的控制器版本 我想把它暴露给 Objective-C 但是它依赖于 我下一步想做什么依赖于我需要 用刷新方法做什么 所以如果我想要 用接口生成器或是核心数据属性 我们有专用属性 你所要做的就是添加这些属性 所以如果你使用现在 展示的IBAction属性
你只需要在i接口生成器中 将刷新方法设置为有效行为
相似的如果你正在使用 全系统基础关键值属性 或者是Cocoa绑定属性 你只要添加动态调整器就可以了 这将告诉Swift 这个属性实施过程中 通过全系统关键值 可以在线调整
但是如果你想要将某个特殊方法 或是属性暴露给 Objective-C 你总是可以使用plain-old at-objc调整器 或是objc 属性 对不起 这将会把方法或 objective暴露给 Objective-C 这不需要任何附加语义
这个objc属性在其它事情上也有用 在Objective-C中 这个objc属性会 为你指出一些不可见的事物 如果我想要非寻常返回类型 的跨版本刷新 那么我将会看到错误信息 “因为返结果类型不能在 Objective-C中体现 所以该方法无法在objc中标识”
所有这些规则都包含在 “用cocoa使用Swift and Objective-C” 手册这本手册中 可以访问 developer.apple.com/Swift在线查找
现在我们已经介绍了默认值 还介绍了如何重新定义这些默认值 以便让我们的代码更加符合ObjC 但是如果你碰到相反的问题呢?
让我们来看看这个类:计算器控制器 它有两个方法:“执行 操作” 其中一个有一种类型的封闭包 另外一种有不同种类的封闭包 好吧 Swift能够基于参数类型快速区分 这两个方法 但是Objective-C 不是这样工作的 在Objective-C中 不能通过类型 只能通过名称区分方法
在这里Swift知道这是个问题 它会给你发送错误信息
现在你总是可以使用ObjC 属性的选择器形式 来修正这个错误 所以如果我编写了这个代码 那么当我从Objective-C接入它时 我就将按钮方法 重命名为执行二进制操作 顶部的方法还是名为执行操作
在Xcode 7中为这类问题 我们添加了其它解决方案 即non-ObjC属性 就像你所想到的 这会使用一些非正常 暴露给Objective-C的东西 并且防止它被这样暴露 你可以将 non-ObjC赋予任何方法 属性子脚本或初始化器
那是数量非常庞大的 Objective-C和方法 但是低级语言怎么办?
来看看C语言
这里有些人不太高兴了 我们有一个函数指针的幻灯片
函数指针是C语言用户用来回调的 这意味着它们类似于闭包 但是它们不能携带任何附加状态 我说的是什么意思呢?
我用Swift试图 调用C函数开放函数 它有很多的参数 你不需要知道所有的参数 其中一个是回调参数 在这个回调中我做自调用 所以它必须储存在这个闭包 后面访问的某个部分 这是我们所谓的携带状态的闭包 当你试图使用这个闭包 用这个API你收到一个错误信息
现在在Swift1.2中 函数指针不是非常有用 在顶部显示的是C类型 它透明的进入Swift C函数指针类型 你可以把它传过来 但是不能再做更多的东西了
Swift 2.0中我们只是增加了 标识为convention-C 标识为 convention-C的闭包 你能在Swift中创建传递它们 甚至是调用它们 这意味着你可以在Swift中 访问全部的C APIs 以前你可不行
所以我们做了 两件小事以提升Swift C和Objective-C 之间的桥接能力
但是今年我们还有非常重要的新特性 在语言桥接方面 具有非常巨大的影响
最重要的当然是错误处理
如果你还没听说过 错误处理模型我们准备了很多 关于Cocoa的NSError 样式和规则的课程 以及围绕这些话题的约定 并分享我们从建立这样一个新特性 中学到的知识 这个新特性用 “throws“关键字表示 这会覆盖今天上午课程的许多内容 “有什么新Swift” 如果你还没有使用它 我强烈的建议你以后试试 看看错误处理机制是如何工作的
但是我重点要讲的是它在两种语言 混编时的应用 你要明白这并不是仅仅从 Objective-C映射到Swift 这也是Swift类库 如何暴露给Objective-C 这是双向映射
让我们仔细看看这里的返回类型 在Objective-C中错误约定为 返回无效值视为发生错误 当填写“out error“参数时 会这样
然而在Swift中这完全 包含在错误处理模型中了 所以在Swift返回类型中你会看到 非选择性的对象类型
相似的在Objective-C 当没有事务被视为失败事务时 你将得到一个布尔返回值 同样的在Swift的错误处理中也有 你将得到一个void返回类型
现在在这些 Objective-C的例子中 既有多参数的 也有只有一个错误参数的 但是还有一些case中的 方法只有一个参数 你将得到像 “请检查资源可查到并返回错误” 这样的提示 在Swift中如你所见 既然我们已经知道 使用“throws”关键字 方法可以返回错误 我们将砍下最后三个单词 只为你!!!
现在所有的都会有的 当你使用 NSError-star-star类型 当你真正的使用NSError约定 的基本格式 其它情况下会发生什么? 我们只是让事情保持像这样 在Objective-C如果你有 NSError参数通常 它会以可选的NSError 参数出现在Swift中 你为正在使用的任何API 来恰当的处理它
记住NSError参数符合 Swift错误类型协议 所以你也可以用Swift自己的 处理机制使用NSError参数
这些都显示Swift已经准备好处理 所有来自Objective-C的报错
但是如果我从 Objective-C调用一个方法 并且它是一个Swift方法 产生的Swift错误呢
现在当然了我们需要这个 然我们看看它的原理
这里我有一个名为“请求错误” 的错误类型 它是一个用Swift的错误 系统定义的新类型 它符合错误类型协议在这个案例中 它是一个枚举只有一种可能性
在方法中使用这个错误很容易 我再定义一个“发送请求”方法 用“throws”关键字标识它表示 它可以失败然后当我触发失败条件时 实际调用了“throw”
现在我要在 Objective-C调用这个方法 它应该能行 怎么样
首先是方法的名字 发生了变化 不再只是“发送请求 现在是发送请求错误”了 就是你将使用的名称 前提是你的Objective-C 代码从“发送请求这个方法开始 另外在此基础上我们刚刚使用了 plain-old NSError 类型以及我们在Swift 中产生的错误
除此之外错误类型确实包括有用的信息 如果我们输出带着这个错误的域和代码 我们将会知道它原来是类型 以及我们以前看到的 enum类型的原始值
现在这里将会有一个 更加有趣的事情发生 我用ObjC 属性去标记 enum类型的数据 这是我们添加在 Xcode 6.3的一个功能 如果你在enum上用 ObjC 属性标记 然后它就会输出到你所产生的头文件上 这个头文件暴露了swift类的 Objective-C的一面
在Xcode...抱歉 在Xcode 7中 我们已经添加了一个更有趣的 小功能在这儿 这是一个包含错误类型协议的enum 因此我们也将会产生一个字符串常量 去表示错误域
现在所有比较的大的 错误都已经被你在swift中标定了 你可能想为自己的类去使用和运行这个 但是随后从 Cocoa 回到其余的SDKs 感到不足的错误 但是别担心我们将会全力帮助你的 因此如果你出席今天早些时候的演示 你可能已经见过这种 检查资源的可达性 并且捕捉不同错误情况的预检措施 现在错误的类型之一 已经被列为 “NSURLError文件不存在” 那是一个来自Cocoa的错误 为什么要使用快速符号去显示?
好了我们已经在整个SDKS中 使用了最常见的错误类型 这样可以让你利用 Swift自己的捕捉语法去使用它们 因此在这儿你可以使用各种各样的错误 你应当远离的通常的想法就是 当你在使用Objective-C中的时候 错误就应该会就像NSError 而当你在使用swift的时候 它们也就应该想swift的错误 事情应该只是工作
因此这只是在过去的一年中 我们在互操作性所做的一些改进 所以说到我们在Objective-C 方面所做到的改进 我想把它交给 道格
谢谢你 约旦 那么今天我们将会讨论 我们这一年添加在 Objective-C方面的三个特性 这些特性能够让你 更好的使用 Objective-C去编程 能够让Objective-C APIs更加的优秀 让他们更好的映入到swift中 同时提高你在使用 Objective-C的静态类型的安全性 我们将要讨论的第一件事情就是 Objective-C的 nullability 来观察一段 Objective-C的代码 有很多的指针 这里面哪一个可以是零?
代码不会告诉你
如果你继续去阅读文档 如果你今天幸运的话 它今天可能会告诉你
你应当去写一些测试 看看它可能的表现的 行为或者可能的猜测 但是那并不是一个好的方法 在这些地方可能会缺少一些信息 当我们去年推出swift的时候 在这些实质上意味着我们不知道的 默认打开的选项中 信息的缺乏表现的更加的明显 在swift的一面它可能是零
所以我们并没有感到太高兴 在发布Swift 1.0之后 我们在自己的核心框架内 编写了成千的指针 去告诉那些指针可能为零的编译器 经过编辑之后的接口变得更加的简洁 现在我们使用可选择的类型 零是你确实必须处理的一件事情 其它的一切都是不可选择的
这仍然不是那样的美好 因为这些知识被编译成编译器 这不是你所能完成的事情 所以对Xcode 6.3来说我们为 Objective-C引入了可空限定符
所以你可以把可空限定符 添加到C/Objective-C 的指针中 去描述是否可以接受零状态
当然你的应用程序 确实可以做更好的通讯 它接受零么? 这说的通么? 它能够帮助我们的工具 做出更好的静态检查去 捕捉运行时表现出来的bug 它能够在你的 Objective-C APIs中 让你的swift表现的更好
现在这儿有三个可空限定符 Nullable 这表明可能是空的指针
这个当然映射到一个Swift选项中
然后那儿有一个非零 这就表明零并不是一个有意义的值
现在对于一个非零指针来说 它可能最终在Objective-C 程序中最终变成0 可能它就是因为某些时候 我们在传递0的时候 零通过传递 而这个时候已经开始运行过了 编译器并不会因为非空的注释 改变它生成代码的方式 这就表明了应用程序作者的意图就是 零在这儿不合情理
我们也有三分之一的 null-unspecified限定符 这在无论是nullable还是 非零的情况下实际上都是正确的事情 如果我们对于指针一无所知 我们把这些映射到 那些你就可能会得到的 相同的默认打开的选项中
关于可空限定符 最重要的事情就是 我们已经在我们整个SDKs去推出了
好 所以不是 单纯的覆盖几个核心框架 我们已经覆盖了 SDKs的绝大部分 所以这给出了一个非常好的 在其他地方都有关系和 non-optionals 正确optionals的 swift经验 对于你的 Objective-C代码来说 这意味着你已经开始看到 已经被误用的APIs的新的警告 因此 比如你看到一个你已经把 零传送到你并不期望的路径的警告 这不是应用程序协议的一部分
现在可能传递过一个以前运行过的零 它可能会继续工作 但是你应当注意这些警告 因为这些应用程序的作者已经告诉过你 你不应当在这儿传递零这里必须要小心 因为它将来可能会改变
现在,比方说你想添加 可空限定符到你的头文件中去 这个开始的地方就是被编辑的区域 因此这些将会被“NS-assume non-null begin” 所描述 NS-假设非空结束 包括你用的这些宏的头文件
这样做就是允许编译器 对未注明的指针 去采用默认的假设 所以如果你有一个单级指针 那么将会被假定为非空 因为我们发现 对于我们绝大多数的APIs来说 零并不是一个有意义的值
另一个有趣的特殊情况下就是 这里是一个 NSError-star-star 参数当你在对Objective-C 的错误进行处理的时候 这些可以在两个级别上被认为是空的 因为这是你和他们为空性工作的方式
现在默认是良好的 他们应该承担大部分的情况下 但是这就意味着 你必须去注释异常的情况 所以我们把这些超视图的 属性标记为nullable 当然不是每个视图都有一个超视图 零在这儿是有意义的
冲击测试的时间有个可空参数 你不需要通过一个事件去做冲击测试 当然结果是可空 因为零在这个地方是有意义的 这意味着我们没有击中任何东西
现在这就是null-unspecified 出现的地方 说你正在编辑一个头文件
你将会遇见一些 一直都存在的很奇怪的事情 你不知道它 它没有被记录下来 可能它正在做一些特别有趣的事情 这些事情传递着可能会或者不会工作 它五年之前退役时才能回答的零
仍然有使用空未指明的很大空间 只是要把它标记成空未指明 这就意味着“我考虑过这个问题 但是我没有得出答案” 最好的事情就是在swift中 保持它默认未开的选择
保持它是空未指明的 你可以稍后再回来 所以当编辑的时候吗你确实像 更早的得到一些好的广度 去让你的 APIs 更好更快
现在 当你去到C 事情就会变得有点模糊 所以我们有了所有相同限定符 但是他们之前需要下划线
现在这些双下划线的关键字这些限定符 可以被用于任何地方任何指针 这个地方有个重要的规则就是 限定符适用于右指针 constor或者volatile 将会去应用那个指针 这对于这样的 参数外指针是nullable的 参数外指针值是nullable的 多级指针是非常重要的 因为只要参数num的值也是 零你就可以在这个参数中传递零
内部指针是空的因为当你传递数组时 所有的使用CF数组的值 都必须是非空的
这就是我们要讲的关于可空的东西 今年我们已经把它推送到 我们的 SDKs 中 所以你能够在 在Objective-C 和 Swift中获得更好的体验 我们强烈的推荐你使用它 去提高你自己的 Objective-C APIs 特别是为了一个更好的 Swift 体验
好了 让我们开始下一个特性 这是一个大的
对于Objective-C来说 是一个重量级的泛型
现在这个特性的原型 它其实是相当容易去激励的 集合
这里我们有 subviews的NSArray
数组中的是什么? 我们不说在数组中的东西 我们把这个拿入到 Swift中你说 嗯 这是任何对象的数组 它仍然没有告诉我任何事情
我已经投了很多 那就是他告诉我的 当然我们有这种常见的 请求类型的集合 因为人们总是说想说 我有一个数组的观点 我有一个从字符串关键字映射到 与图片相关的关键字的字典 这可能是过去十年当中 要求最高的 Objective-C特性 所以现在我们最终推出 重量级泛型的Objective-C 所以这是一个可以改善 你的APIs的表达性 的一个最通用的语言特性 这让集合的方式更容易去使用 现在我们有了所有静态安全集合类型
让我们看一看
所以这是我们的 subviews的属性
这是一组UI视图 我们只是把UI-view-star UIV指针放置在尖括号中 相同的语法你已经看到过了 哎哟 抱歉
相同的语法你 可能从swift和C++ 或者C-Sharp等语言当中看到过 是的 我们完全清楚 尖角括号是引用协议限定符 别担心 我们知道这一点
所以这就向 Object-C 中 引入了更多的类型信息 当然这一点反映到Swift中 就有了更多优雅的类型信息 但我真正想谈谈 其对Objective-C的影响 因为这一功能对于 Objective-C来讲确实有用 现在我们来谈谈类型安全
下面是一个例子 所以我要取得任何一个 URL 或 NSURL 的路径组件 然后将其放入 进入一个阵列的 URLs 之中 如果我不知道这个应用编程接口 这种做法看起来就近乎是合理的 而且要等一段时间我才能 得到运行错误的信息 一个无法确认的选择器会指出不对 我在使用路径组件的方式上 犯了一个很大的错误 有了类型集合体并且 当然 我们在我们的整个软件开发包中 推出了很多类型集合体 现在你就会及时得到一个警告 在错误发生时 告诉你到底你做错了什么
还有许多其他情况比如说 我要建立一个 NS 字符串组成的 不可变阵列可我傻傻地又要 往那个阵列中加个东西 却没有先把它变成一个字符串
编译器将会告诉我不对 你不能把一个 NSNumber 放到这个 NS 可变字符串阵列中 这不合理
实际上编译器 对于此处与 Cocoa 集合体有关 的语义有着相当深入的了解 现在我们看看这里的例子 我们有一个视图阵列 我们还有一个应答阵列 我们将视图阵列中的元素 一个个分配到应答阵列中
没有问题 因为每个视图也是一个应答 看起来挺好 没有问题
让我们用一个可变的变式 来做同样的事情
所以我们用那个存储的可变 视图阵列将其元素分配给 存储的可变应答阵列
这里有个陷阱 这个陷阱是 当然 我可以对 我所存储的应答进行转换 在其中放一些不是视图的应答元素
这样对之后的某个过程 事情就会变得非常混乱 那个它正在查看的视图阵列 中有个一个视图控制器元素不是视图
编译器也了解这一点 它会在程序初始化时抱怨在这里 虽然用不可变阵列来完成这一任务 很安全因为他们不会 在你不注意时改变可用其变体可变阵列 来做这些就不安全
好你其实已经亲眼见过你需要的一切 使你能够在你的整个应用程序中 使用轻量泛型且类型化的集合体 但是现在来看看 我们怎样在Foundation 中 使用这一方法
来实际上创造类型化的集合体 因为这里的该功能是泛型的 类型化的集合体是其结果之一 所以在这里我们有 NSArray 因为你习惯于见到它
现在我们要 基于存储在 NSArray 中的
对象的类型将其参数化 这次我们又要使用尖角括号 这里我们只是引入一个名字 这一名称 我们可以在整个界面上使用 当然索引处是对象 返回的也会是对象类型 如果我们在这里添加其他的方法 当你用一些对象来将你的阵列初始化 那个 C 阵列就会包含对象 通过添加对象来使用阵列 你放入一个新的对象 你获得一个NSArray阵列的对象 所以它的组造非常非常顺利
当然这也适用于类别和扩展
在这里我们有一个NSDictionary 类别以密匙类型和对象类型 进行参数化而且我们还在这里 使用对象类型替代密匙类型 在这里接受一个密钥类型 返回一个可以为 null 的对象类型 因为这里 当然空值是有意义的 因而我们要使我们的应用程序接口中 包含这一信息
现在当然还有一些 现有的在 NSDictionary 和NSArray等等基础上定义的 类别也许你自己就会有一些 那些会和过去一样可以继续使用 他们不能以任何方式访问类型参数 但他们也根本不会改变行为 他们将会像过去一样继续发挥作用
这使我想到了向后兼容性
所以整个轻量泛型功能都基于 一个类型擦除模式之上 这意味着编译器拥有全部这些 丰富的静态类型信息但当编译器要 生成代码时它就会清除这些信息 这对 Objective-C 来讲 有很大的好处 我们不需要对 Objective-C 的运行 进行任何更改就可实现这一功能 这意味着我们可以在类型集合体中 推出泛型你可以在你的所有 应用程序中采用之 这不会影响你将你的应用 部署回各种现有的 操作系统上的能力
这些从那个描述中看起来不太明显 当然我们也不会 以任何方式改变程序共同生成 我们不会在Objective-C中 添加运行中的检查 这种做法在 Objective-C中没有意义 我们只是要保持 完全的二进制码兼容性 因此采用此功能用好那些警告 因为他们能帮助你 避免犯下可怕的错误
你可以非常 非常 非常缓慢地采用之 我觉得这是最好的说法 所以除了二进制代码的兼容性之外 我们还要提供源代码的兼容性 因为我们是通过我们的 软件开发包来推出这些功能的 我们不想让你不得不 更新你所有的源代码 以便在各处都使用这一功能 我们希望你逐步采用它 哪里你觉得合理你就在那里使用它 因此我们在该语言中 提供这些隐式转换 使你可以添加类型参数或将其去除
好吗?另外这样做 不会带来任何运行成本 但在你需要时 它可以让你 进入和离开泛型系统 因此你所有的新代码都可以 用泛型来编写 而且如果你不想要去碰你旧的代码 那完全没有问题这不会改变
好吧 我们还要谈谈最后的一个功能 这一功能比较酷
是这种的类型
实际上来自于我们 在轻量泛型方面所作的工作 于是我们起步之处当然是 将不具类型的集合体用于子视图 也有这样的代码先去抓取一个视图 之后向其发送一些信息 此代码是好的今天仍能运行
我们进行下一步做了这些注释说 好吧 子视图包含用户界面视图 所以我们被警告了
编译器完全有正当理由 来发出这一警告
它现在知道 第一个子视图是个用户界面视图
它不可能知道 你知道那是一个用户界面按钮 且会实际上对这一选择器做出反应
因此虽然编译器是正确的 可对所有这些代码 发出警告并不一定有什么用处 你会得到大量的警告 其中大部分都是良性的 你会需要在各处使用各种转换
这真的迫使我们考虑 ID 以及如何将它作为 一个应用程序接口合同
所以我们在这方面举个小的简单的示例 让我们来谈谈 NSApp 这是 Cocoa 中的那个全球变量 使你能够访问 你的NSApplication实例 现在这真正的意味是NSApp 是NSApplication的 一个子类别 但我们无法向类型系统解释这一点 使用 kindof 类型我们可以 在Objective-C中准确表达这一点
这意味着什么? 这意味着NSApp是某种应用程序 所以我们要赋予它 一些有限的行为 如ID
所以我有了一个NSApp当然我可以 将它转换成一个 NSObject 因为每个NSApplication 都是一个 NSObject 在这里重要的部分 也就是类似 ID 的行为 是将 NSApplication 隐式向下转换成 你的 MyApplication子类别
这样好 我们想要这种行为模式是因为 这就是NSApp一直的工作模式 现在我们不会允许的 是一些愚蠢的交叉转换 您试过在一个字符串中 使用 NSApp 吗? 这不是一个NSApplication 且永远也不会是 所以你可以在那里提出一个警告
当然与此同来的是一种想法 你可以与NSApp交换信息 并 得到NSApplication中的 所有方法其各种超类别和其各种子类别
现在使用kindof类型 我们实际上发现 这比 ID 更有用的多 因为它会在应用程序接口合同中 给你更多的类型信息 这一点对 Swift 和 Objective-C来讲都很好 所以在这里我们有这个 NSTableView 方法 有列行和 makeIfNecessary 它总是返回到 ID 因为这一隐含的向下转换类型的行为 是重要的 那么现在我们可以将其重 写成一个kindof NSView 所以返回某种NSView 而从 Swift 来讲 现在我们要返回 一个选择性的 NSView 这对 Swift 来讲 是个正确的 应用程序接口且它可以在 Objective-C中完美地工作 让我们将其带回我们最初的 有关轻量泛型的例子 这里我们有我们的各种子视图称为 UIViews的一个NSArray 好吧现在我们可以说它是 一个NSArray的kindof UIViews 这样我们就在Object-C和 Swift中得到了一个更强大的 应用程序接口 获知这一属性是什么会容易很多
但你不会造成任何虚假 的警告 因为你依旧会有 从 ID 而来的好的隐式的 向下类型转换行为
希望这一点儿会让你提出一个问题
我真的该在应用编程 接口中使用 ID 吗?
多年以来我们实际上 一直在推出很多功能 在各种重要的情况下 比 ID 能够给出 更为具体的类型信息
且在我们推出Arc 的同一年 我们推出了 instance 类型 用于让你调用的方法 返回与 self 相同的 动态类型
今年我们正在推出类型集合体 这将消除 ID 的很多用途 从我们自己的应用编程接口我们 一直在推出这些功能 当然当你采用这一功能时 在你自己的应用编程接口上也是一样 我们现在从 kindof X 通过隐式向下转换 谈谈 X 的任何子类别 所以你可以保持你代码继续工作 起码所有那些实际上 起着作用又没表现怪异的代码 但是会有一个更好应用编程接口合同 而且各种协议已存在于 Objective-C中很长一段儿时间 而使用某个协议的 ID是明白地说 我不在乎一个类别的类型是什么 它只是必须要符合这一协定
所以有一个大类的用途适合于 ID 那是当你真正的意思 确实是一个任何类型的对象 那就没有任何静态类型 信息可以把这一点 表达得更好 这样这方面的一个典型的例子 是用户信息字典 你用字符串做密匙且 你用 ID 做值 这完全合理 因为对不同的密钥其值会有 不同的类型而这种类型你只能够 动态地确定
让我们总结一下 所以我们对Swift和 Objective-C都做了大的改进 这些语言是一起设计并一起进化 以使其可以完美地一起工作 而Xcode和其支持工具将会帮助你 在这两种语言之间游移 这是对你的工作流最好的方法
我们已经为Objective-C 推出了很多强大的功能 我们强烈建议你 使你的使用Objective-C的 情况现代化 这些新的语言功能 给你提供好得多的应用编程接口 你会在我们的应用编程接口和你自己 应用编程接口中看到这一点 这些新功能还会让你的程序 具有更好的类型安全性 让你能够尽早找出问题 而不用等他们在程序 运行时以可怕的无法 确认的选择器的形式表现出来
且使用这些功能可以 真的使你在 Swift 中的 Objective-C接口变得优美 从而让你编程时 获得最好的 Swift 体验
如需更多的信息请联系我们的传道人 Stefan Lesser 查找相关文档 或者通过我们的网上论坛与我们联系
还有很多有关的课程讲授 Swift 和 Cocoa 中 有什么新的东西 这里有很多很棒的Swift课程 谢谢
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。