ios Swift加载xib文件的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26539849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift proper way to load xib file
提问by B?a?ej
I have some strange problem with loading xib file in swift project. It's so frustrating because I already know how to do it in Obj-C. But since swift is swift so you can't do it like you did.. :/
我在 swift 项目中加载 xib 文件时遇到了一些奇怪的问题。这太令人沮丧了,因为我已经知道如何在 Obj-C 中做到这一点。但是由于 swift 很快,所以你不能像以前那样做..:/
So I have create IconTextFiled.xib and IconTextField.swift. (extends UITextField) In xib I fill field Class in Idenity inspector and in storyboard I do the same for some textFields. So we good to go just add loading from xib to init method? No.
所以我创建了 IconTextFiled.xib 和 IconTextField.swift。(扩展 UITextField)在 xib 中,我在 Idenity 检查器和故事板中填充字段类,我对某些文本字段执行相同的操作。所以我们很高兴将加载从 xib 添加到 init 方法?不。
In objc I would do it like this
在 objc 我会这样做
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"IconTextField" owner:self options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
So I thought if I translate to swift it will be good.
所以我想如果我翻译成 swift 会很好。
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let nib:NSArray = NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self = nib.objectAtIndex(0)
}
But that doeasn't work. I don't know why but it try to create much more object and crash
但这行不通。我不知道为什么,但它试图创建更多的对象并崩溃
Finally I found extension
最后我找到了扩展
extension IconTextField {
class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> IconTextField? {
return UINib(
nibName: nibNamed,
bundle: bundle
).instantiateWithOwner(nil, options: nil)[0] as? IconTextField
}
}
So in ViewController it looks like
所以在 ViewController 中它看起来像
@IBOutlet var password: IconTextField!
override func viewDidLoad() {
super.viewDidLoad()
password = IconTextField.loadFromNibNamed("IconTextField")
}
And again fail. Could you tell me how you load and use xib files?
又失败了。你能告诉我你是如何加载和使用 xib 文件的吗?
UPDATE
更新
Ok following after Daniel anwser
好的,在 Daniel anwser 之后
My current code
我当前的代码
class IconTextField: UITextField {
@IBOutlet var icon: UIImageView!
@IBOutlet weak var view: UIView!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSLog("initWithCoder \(self)")
NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self.addSubview(view)
}
}
Those two var are connected to those views
这两个 var 连接到这些视图
Consoleo output, was a lot bigger and end with EXC_BAD_ACCESS
Consoleo 输出,要大得多,并以 EXC_BAD_ACCESS
2014-10-24 10:09:09.984 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be7bfb0;>
2014-10-24 10:09:09.984 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be7ddf0;>
2014-10-24 10:09:09.985 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be7fa20;>
2014-10-24 10:09:09.985 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be814f0;>
2014-10-24 10:09:09.986 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be830c0;>
2014-10-24 10:09:10.083 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7d183270;>
2014-10-24 10:09:10.084 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7d187cd0;>
2014-10-24 10:09:10.084 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7d189960;>
It should be only two initWithCoder. It seams that func loadNibNamed is calling initWithCoder
应该只有两个initWithCoder。它接缝 func loadNibNamed 正在调用initWithCoder
采纳答案by Daniel T.
This works for me:
这对我有用:
class IconTextField: UITextField {
@IBOutlet weak var view: UIView!
@IBOutlet weak var test: UIButton!
required init(coder: NSCoder) {
super.init(coder: coder)
NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self.addSubview(view)
assert(test != nil, "the button is conected just like it's supposed to be")
}
}
Once loadNibNamed:owner:options:
is called the view
and test
button are connected to the outlets as expected. Adding the nib's view self's subview hierarchy makes the nib's contents visible.
一旦loadNibNamed:owner:options:
被调用view
,test
按钮就会按预期连接到插座。添加笔尖的视图自身的子视图层次结构使笔尖的内容可见。
回答by Sam
I prefer to load from nib, by implementing loadFromNib()
function in a protocol extension as follows:
我更喜欢从nib加载,通过loadFromNib()
在协议扩展中实现如下功能:
(as explained here: https://stackoverflow.com/a/33424509/845027)
(如此处所述:https: //stackoverflow.com/a/33424509/845027)
import UIKit
protocol UIViewLoading {}
extension UIView : UIViewLoading {}
extension UIViewLoading where Self : UIView {
// note that this method returns an instance of type `Self`, rather than UIView
static func loadFromNib() -> Self {
let nibName = "\(self)".characters.split{if let customView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView {
// Set your view here with instantiated customView
}
== "."}.map(String.init).last!
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiateWithOwner(self, options: nil).first as! Self
}
}
回答by Zaldy
You can use this:
你可以使用这个:
##代码##