【问题标题】:Objective -C vs. Swift Custom InitializersObjective -C 与 Swift 自定义初始化器
【发布时间】:2015-05-04 02:08:13
【问题描述】:

我正在开发一个带有自定义类的 Swift 项目。该项目的旧 Objective-C 版本有一个自定义的 init 方法,如下所示。

自定义类的自定义初始化

-(id) initWithURLDictionary: (NSDictionary *) dictionary{
self = [super init]; 
if (self) {
    self.URLDictionary = dictionary;
}
return self;

}

使用此类时,我将使用自定义初始化程序创建对象,然后将自定义类的委托设置为 self。

// Create a temporary dictionary of the feeds, allocate and initialize the FLODataHandler object and set the delegate (me) to self.
NSDictionary *URLTempDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: kFLOCyclingURL, @"FLO Cycling", kTriathleteURL, @"Triathlete", kVeloNewsURL, @"Velo News", kCyclingNewsURL, @"Cycling News", kRoadBikeActionURL, @"Road Bike Action", kIronmanURL, @"Ironman", nil];
self.dataHandler = [[FLODataHandler alloc] initWithURLDictionary: URLTempDictionary];
self.dataHandler.delegate = self;

在 Swift 中我有点困惑。看来我有两个选择。选项 1 会让我在自定义类中创建一个自定义初始化程序。

自定义类中的自定义初始化器

init(dictionary : [String:String]) { self.URLDictionary = dictionary }

过程与Objective-C相同。

let URLTempDictionary = [kFLOCyclingURL : "FLO Cycling", kTriathleteURL : "Triathlete", kVeloNewsURL : "Velo News", kCyclingNewsURL : "Cycling News", kRoadBikeActionURL : "Road Bike Action", kIronmanURL : "Ironman"]

    var tempDataHandler = FLODataHandler(dictionary: URLTempDictionary)
    self.dataHandler! = tempDataHandler

选项 2 没有通过投诉,但似乎不完整。

我不会创建自定义初始化程序,而是简单地执行以下操作。自定义类有一个名为 URLDictionary 的字典属性。

let URLTempDictionary = [kFLOCyclingURL : "FLO Cycling", kTriathleteURL : "Triathlete", kVeloNewsURL : "Velo News", kCyclingNewsURL : "Cycling News", kRoadBikeActionURL : "Road Bike Action", kIronmanURL : "Ironman"]

self.dataHandler!.URLDictionary = URLTempDictionary
self.dataHandler.delegate = self

所以我的问题与自定义初始化程序的需要和使用

有关
var tempDataHandler = FLODataHandler(dictionary: URLTempDictionary)

是否使用

self.dataHandler!.URLDictionary = URLTempDictionary

实现同样的结果?

保重,

乔恩

【问题讨论】:

  • 您能告诉我您是如何在班级中声明 dataHandler 成员的吗?

标签: objective-c swift


【解决方案1】:

初始化器的目的是有效地强制调用者提供数据——而 Swift 通过以 Objective-C 没有的方式强制执行这个契约来帮助你。如果您声明 init(dictionary:),则所有其他继承的初始化程序将不再被继承,并且 init(dictionary:) 成为创建 FLODataHandler 的唯一方式。

因此,如果 FLODataHandler 从一开始就具有 URLDictionary 值至关重要,那么一定要声明初始化程序。事实上,如果它也有一个委托很重要,请改为声明init(dictionary:delegate:)。那是“最佳实践”。

另一方面,两阶段初始化本身并没有什么坏处,即首先创建对象,然后赋予其属性值;并且在现实生活中的 iOS 编程中存在没有真正替代方案的情况(我想到了prepareForSegue)。问题在于它依赖于不可执行的合同,调用者必须以其他方式简单地了解并自愿遵守。

编辑:你似乎也在问是否只是说

self.dataHandler!.URLDictionary = URLTempDictionary

不知何故神奇地创建了一个 FLODataHandler 来占用dataHandler 属性。它肯定不会。在 Swift 中没有任何对象可以神奇地存在,就像在 Objective-C 中一样。如果没有人说过FLODataHandler(...),那么就不存在这样的例子。如果没有人将 FLODataHandler 实例分配给 self.dataHandler,那么那里就没有 FLODataHandler(如果这意味着您试图解开 nil,上面的代码将会崩溃)。

【讨论】:

  • 感谢您的回复。这很有意义。一个后续问题。在 Objective-C 中,我们必须专门调用 alloc 和 init,然后将对象传递给属性。这不是 Swift 的情况吗?行 self.dataHandler!.URLDictionary = URLTempDictionary 是否涵盖了新对象的创建?
  • 不,它没有。但在我看来,那是完全不同的事情。我们谈论的是数据处理程序如何获取字典,而不是如何首先实例化。
  • 我会在我的回答中添加一个注释。
  • 这可能会帮助您阅读我的 Swift 书籍的相关部分:apeth.com/swiftBook/ch04.html#_initializers
  • 请忽略我最后的评论。我错了。我知道现在需要发生什么。我必须初始化对象。感谢所有的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
相关资源
最近更新 更多