问题标签 [designated-initializer]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
ios - 如何在 Swift 中编写 UIViewController 的 init 方法
我无法将 init 方法添加到以下 UIViewController 类。我需要在 init 方法中编写一些代码。我必须编写 init(coder) 方法吗?即使我添加了编码器和解码器方法,我仍然会出错。我也尝试使用不带任何参数的 init 方法,但这似乎也不起作用。
如果我在没有参数的情况下调用 super.init() 方法,则错误是“必须调用超类的指定初始化程序”,如果我传递参数 nib 和 bundle,则错误是“必需的初始化程序 init(coder)”。
即使我添加了 init(coder) 和 init(decoder) 它也不起作用。
objective-c - 如何在 Objective-C 中将超类的指定初始化程序标记为“无效”?
来自Adapting Modern Objective-C 文档:
如果一个类提供一个或多个指定初始化器,它必须实现其超类的所有指定初始化器。
这意味着如果我有一个子类NSObject
有自己的指定初始化程序,比如说
那么我还需要提供 NSObjects 的实现-init
。我应该怎么做才能将-init
初始化程序标记为“无效”,即没有人应该调用它,而是使用它-initWithImage:
?这里的最佳做法是什么?
编辑
我尝试了这里描述的技术。
但是,当我将超类-init
方法标记为unavailable
在接口中时,编译器仍然告诉我需要覆盖超类的初始化程序。
当我尝试其他技术时,即引发异常或-doesNotRecognizeSelector:
在内部调用时-init
,我收到一条错误消息,指出我需要调用我指定的初始化程序之一。
objective-c - 来自 Objective-C 类的非指定初始化器继承
在对类进行子类化并向它们添加不可变变量时遇到问题UIKit
,我做了一个测试项目来弄清楚发生了什么。
我的结论是,如果:
- 我们有一个Objective-C类,它继承自另一个类,具有自己指定的初始化程序(隐式或显式注释)
- 在其初始化程序中,它调用
[self initWithXX]
whereinitWithXX
isinit
超类上的方法 - 我们在Swift 中子类化这个类,添加一个不可变属性(显然必须在实例化时初始化)
- 我们为这个Swift类实现了一个指定的初始化器,它设置不可变属性,然后调用父类的指定初始化器
那么这将导致运行时异常,因为Swift类在调用Objective-C超类的指定初始化程序时会尝试调用initWithXX
并且self
该方法尚未从超类继承,因为我们已经实现了指定初始化程序。
此测试的代码将是:
查看.h
查看.m
SwiftView.swift
异常生成代码
例外
致命错误:对类“Test.SwiftView”使用未实现的初始化程序“init(frame:)”
我这样做的动机是对标准库类(...)进行子类UITableViewController
化MKAnnotationView
并添加不可变属性以包含对它们的注入依赖项,然后需要在子类的实例化时通过将它们传递给自定义指定init
方法来对其进行初始化,并发现这导致了上述意外异常。
在完成了这个实验以确定原因之后,我想我理解它为什么会发生(因为父Objective-C类指定的初始化器正在委托给它自己的另一个指定的初始化器,而不是调用它的超类的初始化器)。很明显,要解决这个问题,标准库应该更改它们的初始化方法以调用超类初始化器而不是self
初始化器,但我可以理解调用self
而不是super
可能是有效的功能,以便允许子类覆盖默认行为,同时保留特定的初始化器. 另外,我想这样的改变可能会导致很多问题,因为许多应用程序可能已经建立在这个功能上,这会破坏它。我想这里的基本问题是Objective-C和Swift之间的语言特性不兼容。
除了使这些不可变变量可变并在第二个初始化阶段设置它们的(非常不受欢迎的)方法之外,任何人都可以看到解决这个问题的任何方法(无论是在 Apple 修复还是代码变通方法方面)?
编辑
这是我的测试项目的堆栈跟踪:
作为明显的上下文,我有一个简单的单视图 iOS 项目,我尝试在我的视图控制器的方法中实例化我的SwiftView
对象。viewDidLoad
编辑
作为额外的问题,这样做的另一个结果是,如果为了使我的子类正确实例化,我要将我的Swift类变量更改为隐式展开的可选:
并通过将我的不可变名称变量设置为来实现缺少的初始化程序(这样我就可以使用我创建的指定初始化程序,但是如果有人使用我必须实现但从未使用过的指定初始化程序,那么导致的崩溃是他们的错),我得到在我用参数实例化对象之后,完全出乎意料的结果nil
SwiftView
name
的值view.name
是nil
(可能是因为在方法最初设置之后调用了init(frame:)
初始化程序)。init(name:)
name
编辑
雷达发布到 Apple
swift - 类层次结构中的便利初始化导致无限递归
我在 Swift 2.0 中有 2 个类的层次结构。这两个类都可以通过传递参数或传递[String: AnyObject]
包含参数的 JSON 字典 ( ) 来实例化。
直接采用参数的 inits 是designated inits
,而采用 JSON 的 initsconvenience inits
具有相同的签名。
convenience
init inSubThing
不允许在 super 中调用同一个 init,如果我在 self 中调用,会导致无限递归,因为这两个方法have the same signature
。
如果我让两个 json 初始化designated
,我不能调用self.init(name:)
in Thing
,我将不得不在两个初始化器中重复相同的代码Thing
。
解决这种情况的最佳方法是什么?
ios - 为什么我必须为我的程序化 UIViewController 子类的 init(coder aDecoder) 继续声明相同的必需但未实现的初始化程序?
也许只有我一个人,但我发现 swift 的某些方面……至少可以说是迟钝的。
我大部分时间不使用 Interface Builder,因为我喜欢使用PureLayout
. 所以我希望创建一个UIViewController
子类,比如说PureViewController
,它有一个init
没有参数的方便:
但这不行,因为 XCode 告诉我我还必须实现init(coder aDecoder: NSCoder)
. 好的,没关系!这就是我制作这个类的原因——所以我不必为子类再做一次。
好的,现在这是我不明白的。
我定义了一个SomePureViewController : PureViewController
带有初始化器的子类init(viewModel:ICrackersViewModel)
...
但它仍然希望我定义相同的愚蠢初始化程序,直到王国来临!
现在我明白了这个想法 -init(decoder)
我的子类中没有,即使它是在其父类中定义的。
也许我一直在处理这个问题,UIViewController
但以前从未注意到它。
我的问题如下:
- 我做错了什么导致这种行为吗?
- 除了继承之外,有什么方法可以避免重复自己吗?
- 是否有计划改变这种情况?
objective-c - 指定初始化器,请澄清。
现在我已经有这个问题困扰我很长一段时间了,我真的需要有人为我澄清这个问题。
1)当一个子类的init方法调用它时,编译器如何确定指定的初始化方法?因为据说它是覆盖率最高的一个。
2)当使用多个init方法进行子类化时,每个类都有自己指定的初始化方法吗?对问题 2 的回答也有助于理解这一点。
3) 当多个类确实有一个指定的初始化器时,其他 init 方法如何在他们的类中调用指定的初始化器?为什么他们也不调用任何其他初始化程序?为什么指定初始化器?它有什么特别之处?
ios - 指定初始化器?
苹果文档中所说的这句话是什么意思:
有时,超类的指定初始化器对于子类可能就足够了,因此子类不需要实现自己的指定初始化器。其他时候,类的指定初始化程序可能是其超类的指定初始化程序的重写版本。当子类需要补充由超类的指定初始化程序执行的工作时,通常会出现这种情况,即使子类没有添加它自己的任何实例变量(或者它添加的实例变量不需要显式初始化)。
是不是说我不必为子类创建指定的初始化程序,而超类指定的初始化程序就足够了,如果是这样,子类的属性将如何初始化?如果允许,在什么情况下?那将如何运作?
此外,如果您覆盖 DI,您如何从子类调用该方法,因为父类具有与您相同的 DI?需要补充工作是什么意思?
ios - 为什么不调用指定的初始化程序
根据文档,应该始终调用指定的初始化程序,但是当我尝试在没有权限的情况下获取用户的血型时,NSError
会创建一个但它的指定初始化程序(- [NSError initWithDomain:code:userInfo:]
)永远不会被调用。
我正在使用的代码是:
Obs:我知道指定的初始化程序没有被调用,因为我已经混合了它。其他方法如- [NSFileManager contentsOfDirectoryAtPath:error:]
预期的那样运行。
为什么会这样?我错过了什么吗?我应该打开雷达吗?
objective-c - 创建新的指定初始化程序时必须重写 init 吗?
我已经阅读了很多关于指定初始化器和便利初始化器的内容,objective-c
并且觉得我对它们的使用方式和原因有很好的理解。我只有几个悬而未决的问题,一个真的。
假设您有一个直接继承自的类,NSObject
并为它创建了一个指定的初始化程序。
我意识到您现在可以使用NS_DESIGNATED_INITIALIZER标记您指定的初始化程序,但我想知道这是否意味着它会强制您在同一个类中分别首先通过调用您指定的初始化程序来覆盖 init?
其次,如果您不使用这个宏,那么在调用指定的初始化程序时不显式覆盖 init 可能意味着什么?我意识到编译器不知道哪个是指定的初始化程序,所以这会不会有什么不好的事情发生,当你为你的类创建一个新的指定初始化程序时,重写 init 是否只是一种好习惯?
编辑:我只想进一步澄清这个问题。我见过一些优秀的程序员没有添加不同的方法来覆盖 init 的例子,尽管他们添加了他们自己制作的指定初始化程序。当我问你是否应该重写 init 时,我的意思是除了创建你自己的特定指定初始化程序之外,它当然应该调用它的超类的 init 方法。我见过一个好的程序员不这样做,所以我想知道你为什么要这样做。
xcode - 检查 xcode 中的指定初始化程序
有没有办法找出 Xcode 中超类中指定的初始化程序?
我输入 super().init.. 然后,Xcode 显示超类的所有初始化程序。我想知道是否有任何标志或符号指出哪个是指定的?
也是一个快速的问题。子类中的指定初始化程序(DI)只允许调用超类中的便利初始化程序(CI),因为超类中的 CI 最终将调用超类中的 DI。如果我错了,请纠正我,谢谢。