欢迎来真孝善网,为您提供真孝善正能量书籍故事!

【译】:目标实现策略解析

时间:11-22 名人轶事 提交错误

各位老铁们好,相信很多人对【译】:目标实现策略解析都不是特别的了解,因此呢,今天就来为大家分享下关于【译】:目标实现策略解析以及的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!

2016 年10 月12 日

Objective-C 中的id和 Swift 中的Any

使用Objective-C API 时,Swift 3 的接口比以前的版本更强大。例如,Swift 2 将Objective-C 中的id 类型映射到Swift 中的AnyObject 类型,并且通常只能保存该类型的值。 Swift 2 还为AnyObject 提供了一些桥接值类型(如String、Array、Dictionary、Set 和一些数字)的隐式转换,以便我们可以像NSString、NSArray 或其他基本集合类一样轻松使用它。 Swift 中的原生类型。这些转换与语言的其余部分不一致,导致很难理解什么可以用作AnyObject,从而导致错误。

在Swift 3 中,Objective-C 中的id 类型现在映射到Swift 中的Any 类型,它可以表示任何类型的值,无论是类、枚举、结构还是任何其他Swift 类型。这一变化使得Swift 中的Objective-C API 更加灵活,因为Swift 定义的值类型可以传递给Objective-C API 并作为Swift 中的类型获取,从而无需手动“装箱”类型(我理解为转换,解袋)。这些好处也扩展到了集合类:Objective-C 中的集合类型NSArray、NSDictionary 和NSSet 以前只接受AnyObject 类型的元素,现在可以保存任何类型的元素。对于Swift 中的哈希类集合,例如Dictionary 和Set,有一个新类型AnyHashable,它可以保存Swift 中遵守Hashable 协议的任何类型的值。简而言之,某些类型从Swift 2 到Swift 3 的映射关系发生了如下变化:

图片取自Apple 官方博客通常情况下,您的代码不需要进行大量更改来适应此更改。 Swift 2 代码中存在的AnyObject 值类型可以通过隐式转换转换为Any,并继续在Swift 3 中工作。但是,有些地方需要更改声明的变量和方法类型才能在Swift 3 中进行编译。此外,如果您的代码显式使用AnyObject 或Cocoa 中的类(例如NSString、NSArray 或NSDictionary),则由于对象和值类型之间的隐式差异,您将需要引入更显式的转换以用作NSString 或字符串。 Swift 3 中不允许进行转换。Xcode 中的自动迁移器将进行最小的更改,以确保您的代码从Swift 2 成功编译到3,但情况并不总是有利的。本文将指出您可能需要进行的一些更改,以及更改代码以使用id 作为Any 时需要注意的一些问题。

重写方法和遵守协议

创建一个继承自Objective-C 类的新子类并重写其方法,或遵守Objective-C 中的协议。当父类的方法使用Objective-C 中的id 类型时,此时应该修改子类方法的类型。一个常见的例子是NSObject 类的isEqual: 方法和NSCopying 协议的copyWithZone: 方法。在Swift 2 中,您可以创建一个遵守NSCopying 协议并继承自NSObject 的新子类,如下所示:

//斯威夫特2

类Foo: NSObject, NSCopying {

覆盖func isEqual(_ x: AnyObject?) -Bool { . }

func copyWithZone(_ zone: NSZone?) -AnyObject { . }

}在Swift 3 中,除了将方法的命名从copyWithZone (_ :) 更改为copy (with :) 之外,您还需要将这些方法接受的参数类型从AnyObject 更改为Any。如下图:

//斯威夫特3

类Foo: NSObject, NSCopying {

override func isEqual(_ x: Any?) -Bool { . }

func copy(with zone: NSZone?) -Any { . }

非类型集合

属性列表、JSON 和用户信息字典在Cocoa 框架中很常见,它将这些表示为非类型化集合。在Swift 2 中处理此类数据需要使用AnyObject 或NSObject 构造Array、Dictionary 或Set,并依赖隐式桥接转换来处理值类型:

//斯威夫特2

结构体状态{

var name: 字符串

var abbreviation: 字符串

varpopulation: 整数

var asPropertyList: [NSObject: AnyObject] {

var result: [NSObject: AnyObject]=[:]

//隐式转换在这里将String 转换为NSString.

结果["姓名"]=self.姓名

结果["缩写"]=self.缩写

//.这里将Int 转换为NSNumber。

结果["人口"]=self.population

返回结果

}

}

让加利福尼亚=州(name:"加利福尼亚",

缩写: "CA",

人口: 39_000_000)

NSNotification(name: "foo", object: nil,

userInfo: california.asPropertyList) 或者,您可以使用Cocoa 框架中的集合类,例如NSDictionary:

//斯威夫特2

结构体状态{

var name: 字符串

var abbreviation: 字符串

varpopulation: 整数

var asPropertyList: NSDictionary {

var 结果=NSMutableDictionary()

//隐式转换在这里将String 转换为NSString.

结果["姓名"]=self.姓名

结果["缩写"]=self.缩写

//.这里将Int 转换为NSNumber。

结果["人口"]=self.population

返回结果.copy()

}

}

让加利福尼亚=州(name:"加利福尼亚",

缩写: "CA",

人口: 39_000_000)

//NSDictionary 然后在这里隐式转换为[NSObject: AnyObject]。

NSNotification(name: "foo", object: nil,

userInfo: california.asPropertyList) 在Swift 3 中,不再支持隐式转换,因此上述两段代码都无法按原样工作。 Xcode中的迁移器可能会建议你使用as来一一进行类型转换,以确保这段代码能够正常工作,但还有更好的解决方案。 Swift 现在导入Cocoa API 来接受Any 或AnyHashable 类型的集合,因此我们可以使用[AnyHashable:Any] 而不是[NSObject:AnyObject] 或NSDictionary 声明集合类型,而无需更改任何其他代码:

//斯威夫特3

结构体状态{

var name: 字符串

var abbreviation: 字符串

varpopulation: 整数

//此处将字典类型更改为[AnyHashable: Any].

var asPropertyList: [AnyHashable: 任何] {

var result: [AnyHashable: 任何]=[:]

//不需要隐式转换,因为String 和Int 是子类型

//Any 和AnyHashable

结果["姓名"]=self.姓名

结果["缩写"]=self.缩写

结果["人口"]=self.population

返回结果

}

}

让加利福尼亚=州(name:"加利福尼亚",

缩写: "CA",

人口: 39_000_000)

//.您仍然可以在此处将其与Cocoa API 一起使用

通知(name: "foo",object: nil,

userInfo: california.asPropertyList)

AnyHashable类型

Swift 的Any 类型可以保存任意类型,但是Dictionary 和Set 需要的键类型是需要遵守Hashable 协议的类型,因此Any 代表的过于宽泛。从Swift 3 开始,Swift 标准库提供了一个新类型AnyHashable。与Any类似,它充当所有Hashable类型的父类,因此String、Int和其他Hashable类型的值可以隐式用作AnyHashable值。 AnyHashable 类型的值可以使用is, as! 动态检查或动态使用as?转换运算符。 AnyHashable 可以在从Objective-C 导入无类型NSDictionary 或NSSet 对象时使用,并且在纯Swift 中构建异构集合或字典时也很有用。

未链接上下文的显式转换

在某些特定情况下,Swift 无法自动桥接C 和Objective-C。例如,一些C 和Cocoa API 使用id* 指针作为“out”或“in-out”参数,而由于Swift 无法静态确定指针的使用方式,因此它无法自动对内存中的值执行桥接转换。在这种情况下,指针仍将显示为UnsafePointer。如果您需要使用这些无法自动桥接转换的API,您可以使用显式桥接转换,并在代码中使用as Type 或as AnyObject 显式转换。

//对象C

@interfaceFoo

- (void)updateString:(NSString **)字符串;

- (void)updateObject:(id *)obj;

@end //斯威夫特

func interactWith(foo: Foo) -(String, Any) {

var string="string" as NSString //显式转换

foo.updateString(string) //参数导入为UnsafeMutablePointerlet finishString=string as String

var object="string" 作为AnyObject

foo.updateObject(object) //参数导入为UnsafeMutablePointerlet finishObject=object as Any

返回(完成字符串,完成对象)

另外,Objective-C中的协议在Swift中仍然是类约束(只有类才能遵守协议),所以你不能让Swift中的结构体或枚举直接遵守Objective-C中的协议或使用轻量级的Magnitude泛型类。当你需要使用这些协议和API时,你应该像这样显式地将String转换为NSString,将Array转换为NSArray。

AnyObject属性查找

Any 没有与AnyObject 相同的方法来返回对象的描述信息。在Any 对象上查找属性或向非类型化Objective-C 对象发送消息可能会导致Swift 2 崩溃。例如,以下代码使用Swift 2 语法:

//斯威夫特2

func foo(x: NSArray) {

//通过魔法AnyObject 查找调用-description

打印(x[0].描述)

}在Swift 3中,description不再是Any类型对象的方法(通常我们会重写这个方法来获取对象的一些描述信息)。您可以执行x[0] as AnyObject 将x[0] 的值转换为AnyObject 类型以获取其描述:

//斯威夫特3

func foo(x: NSArray) {

//下标的结果现在是Any,需要强制获取方法查找

print((x[0] as AnyObject).description)

或者,将值转换为您期望的特定类型:

func foo(x: NSArray) {

//转换为您期望的具体对象类型

print((x[0] as!NSObject).description)

Objective-C中的Swift中的值类型

Any 可以包含您定义的任何结构、枚举、元组或其他Swift 类型。 Swift 3 中的Objective-C 桥可以将任何Swift 类型的值转换为Objective-C id 类型的兼容对象。这使得在Cocoa 集合中存储userInfo、字典和其他自定义Swift 类型对象变得更加容易。例如,在Swift 2 中,您需要将数据类型更改为类,或者手动加载它们,以将它们的值附加到NSNotification:

//斯威夫特2

struct CreditCard { number: UInt64,expiration: NSDate }

让PaymentMade="PaymentMade"

//我们不能将信用卡直接附加到通知中,因为它

//不是一个类,也不是桥接的。

//将其包装在Box 类中。

类框{

让值: T

init(value: T) { self.value=值}

}

让付款通知=

NSNotification(name: PaymentMade,

object: 盒子(value: 信用卡(number: 1234_0000_0000_0000,

Expiration: NSDate()))) 使用Swift 3,我们不需要Box 类,可以直接将对象附加到通知:

//斯威夫特3

让PaymentMade=Notification.Name("PaymentMade")

//我们可以将信用卡值直接与通知关联起来

让付款通知=

通知(name: PaymentMade,

object: 信用卡(number: 1234_0000_0000_0000,

过期: Date())) 在Objective-C 中,CreditCard 值将显示为id 兼容的NSObject 对象(此处存疑),使用Swift 的Equatable、Hashable 和CustomStringConvertible。如果原始Swift 类型存在,它将实现isEqual:散列和描述。在Swift 中,可以通过动态地将值转换回其原始类型来检索该值:

//斯威夫特3

让paymentCard=paymentNotification.object 作为!信用卡

print( paymentCard.number ) //1234000000000000 请注意,在Swift 3.0 中,一些常见的Swift 和Objective-C 结构类型将桥接为不透明对象(不透明对象到底是什么?),而不是Cocoa 中惯用的对象。例如,Int、UInt、Double 和Bool 桥接到NSNumber。其他大小的数字类型,例如Int8、UInt16 等仅桥接为不透明对象。尽管大多数Cocoa API 使用NSValue 包装的实例,但可变结构(例如CGRect、CGPoint 和CGSize)也桥接为不透明对象。如果您看到一些错误,例如发送到_SwiftValue 的无法识别的选择器,这表明Objective-C 代码正在尝试调用不透明Swift 值类型上的方法,您可能需要手动包装该类的实例,而不是使用Objective-C转换后的类型实例。

选项还有一个特殊问题。 Swift 中的Any 可以容纳任何内容,包括可选的,因此可以将可选类型的对象传递给Objective-C API,而无需先检查它,即使该API 是使用非空id 声明的,很可能会导致A涉及_SwiftValue 的运行时错误,而不是编译时错误。 Xcode 8.1 beta 中包含的Swift 3.0.1 对Objective-C 中的结构和可选值进行数字输入,以解决NSNumber、NSValue 和可选桥接中的上述限制:

* SE0139: 将数字类型桥接到NSNumber 并将Cocoa 结构桥接到NSValue

* SE0140: 当Optional转换为Any时发出警告,并将Optional桥接为其有效负载或NSNull

(以上两篇文章是Github上讲解swift-evolution中Swift类型转换的文章,有兴趣的同学可以阅读)

为了避免向前兼容性问题,您不应依赖_SwiftValue 类对不透明对象的实现,因为Swift 的未来版本可能允许更多Swift 类型桥接到惯用的Objective-C 类。

Linux可移植性

使用Swift Core 在Linux 上运行的Swift 库Swift 使用以Swift 原生编写的Foundation 版本,没有Objective-C 运行时桥。将id 映射到Any 允许核心库直接使用本机SwiftAny 和标准库值类型,同时使用Objective-C Foundation 实现来保持与Apple 平台上的代码兼容。由于Swift 不与Linux 上的Objective-C 互操作,因此不支持桥接转换,例如字符串到NSString 或值到AnyObject。希望在Cocoa 和Swift 核心库之间移植的Swift 代码应该只使用值类型。

学习更多

id 映射到Any 是Swift 语言改进的一个很好的例子,其灵感来自于用户对Swift 早期版本的反馈,并通过开放Swift Evolution 流程的回顾进行了改进。如果您想了解有关id 映射Any 背后的动机和设计决策的更多信息,可以在GitHub 上的swift-evolution 存储库中找到原始Swift Evolution 提案:

* SE-0072: 完全消除Swift 的隐式桥接转换

* SE0116: 将Objective-C id 导入为Swift Any 类型

* SE0131: 将AnyHashable 添加到标准库

最后,Swift 是一种更加一致的语言,并且使用Swift 时Cocoa API 变得更加强大。

所有博客文章

用户评论

眷恋

这篇博客看来很有深度!

    有14位网友表示赞同!

冷眼旁观i

感觉像是要探讨一些关于目标设置的哲学问题。

    有11位网友表示赞同!

孤者何惧

好想知道作者究竟是从哪个角度来解释 "Objective"?

    有20位网友表示赞同!

一别经年

一些人觉得设定目标会让人压力大,这篇文章里可能会讲到怎么避免这种情况?

    有20位网友表示赞同!

鹿叹

目标是人生的关键所在,希望这篇博客能给带来一些启发。

    有18位网友表示赞同!

杰克

从标题看,文章内容应该很实用,可以帮助我们更好地制定和实现目标。

    有5位网友表示赞同!

一笑傾城゛

我一直以来都对如何设定有效的目标比较困惑,期待看看这篇文章有什么新的观点。

    有9位网友表示赞同!

﹏櫻之舞﹏

目标是什么?它意味着什么? 这篇文章正好能解答我的疑问。

    有19位网友表示赞同!

丢了爱情i

人生需要很多不同的目标, 这篇文章可能会涵盖生活的各个方面?

    有5位网友表示赞同!

将妓就计

从 "Objective" 这个词来看,应该会深入探讨目标的本质和意义。

    有20位网友表示赞同!

玻璃渣子

希望这篇文章能激发我思考,去明确自己的目标和方向。

    有9位网友表示赞同!

╭摇划花蜜的午后

文章或许会分享一些优秀的案例分析,让我们学习如何设定和实现目标?

    有18位网友表示赞同!

敬情

感觉像是一篇学术性的文章,应该会有很专业的论述和分析。

    有10位网友表示赞同!

心悸╰つ

越来越多人重视目标管理,这篇文章正好可以帮助我提升自己在这个方面的技能。

    有16位网友表示赞同!

旧事酒浓

在这个竞争激烈的社会中,设定目标非常重要,这篇文章或许能给我一些指引。

    有12位网友表示赞同!

忘故

读完这篇博客之后,我希望能够更有清晰的目标和计划去行动。

    有8位网友表示赞同!

代价是折磨╳

目标不是终点而是旅程的过程,希望能从文章里了解到更深刻的道理。

    有14位网友表示赞同!

古巷青灯

文章标题很吸引人,期待能学习到更多关于目标相关的知识!

    有18位网友表示赞同!

灼痛

“Objective”这个词语很有意思,也让我对这篇文章产生好奇心 。

    有6位网友表示赞同!

【【译】:目标实现策略解析】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活