web-dev-qa-db-ja.com

Swift xibファイルをロードする適切な方法

Swiftプロジェクトでxibファイルをロードする際に奇妙な問題があります。Obj-Cでそれを行う方法を既に知っているので、それはとてもイライラします。しかしSwift is Swiftですので、あなたがやったようにはできません..:/

だから、IconTextFiled.xibとIconTextField.Swiftを作成しました。 (UITextFieldを拡張)xibではIdenityインスペクターでフィールドクラスを入力し、ストーリーボードでは一部のtextFieldで同じ操作を行います。したがって、xibからの読み込みをinitメソッドに追加するだけでいいのでしょうか。番号。

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;
}

だから、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)
}

しかし、それはうまくいきません。理由はわかりませんが、より多くのオブジェクトを作成してクラッシュしようとします

最後に拡張機能を見つけました

extension IconTextField {
    class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> IconTextField? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
            ).instantiateWithOwner(nil, options: nil)[0] as? IconTextField
    }
}

したがって、ViewControllerでは次のようになります

@IBOutlet var password: IconTextField!
override func viewDidLoad() {
    super.viewDidLoad()
    password = IconTextField.loadFromNibNamed("IconTextField")
}

そして再び失敗します。 xibファイルをロードして使用する方法を教えてください。

更新

ダニエル・アンサーの後を追う

私の現在のコード

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)
    }   
}

enter image description here

これらの2つの変数は、これらのビューに接続されています

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;>

InitWithCoderは2つだけです。 func loadNibNamedがinitWithCoderを呼び出していることがわかります

14
Błażej

これは私のために働く:

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")
    }
}

1回loadNibNamed:owner:options:viewと呼ばれ、testボタンは予想通りコンセントに接続されます。ペン先のビューの自己のサブビュー階層を追加すると、ペン先のコンテンツが表示されます。

8
Daniel T.

次のように、プロトコル拡張でloadFromNib()関数を実装することにより、nibからロードすることを好みます。

(ここで説明されているとおり: 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{$0 == "."}.map(String.init).last!
    let nib = UINib(nibName: nibName, bundle: nil)
    return nib.instantiateWithOwner(self, options: nil).first as! Self
  }

}
6
Sam

これを使用できます:

if let customView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView {
        // Set your view here with instantiated customView
}
0
Zaldy