Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中将xib分配给UIView_Uiview_Swift_Xib - Fatal编程技术网

在Swift中将xib分配给UIView

在Swift中将xib分配给UIView,uiview,swift,xib,Uiview,Swift,Xib,在目标c中,它可以在init方法中通过 -(id)init{ self = [[[NSBundle mainBundle] loadNibNamed:@"ViewBtnWishList" owner:0 options:nil] objectAtIndex:0]; return self; } 但当我用斯威夫特做这件事的时候 init(frame: CGRect) { self = NSBundle.mainBundle().loadNibNamed("ViewDeta

在目标c中,它可以在init方法中通过

-(id)init{
    self = [[[NSBundle mainBundle] loadNibNamed:@"ViewBtnWishList" owner:0 options:nil]     objectAtIndex:0];
return self;
}
但当我用斯威夫特做这件事的时候

init(frame: CGRect) {
    self = NSBundle.mainBundle().loadNibNamed("ViewDetailMenu", owner: 0, options: nil)[0] as? UIView
}
显示方法错误时,无法分配给self。 现在我的方法是创建一个视图,并将从nib加载的视图添加到其中。
有谁有更好的主意吗?

这可能是您的解决方案:

Swift 3.x
class func instanceFromNib()->UIView{
返回UINib(nibName:,bundle:nil)。实例化(withOwner:nil,options:nil)[0]为!UIView
}

Swift 2.x
class func instanceFromNib()->UIView{
返回UINib(nibName:,bundle:nil)。将所有者(nil,选项:nil)[0]实例化为UIView
}

用于Swift 4

extension UIView {
    class func loadFromNibNamed(nibNamed: String, bundle: Bundle? = nil) -> UIView? {
      return UINib(
          nibName: nibNamed,
          bundle: bundle
      ).instantiate(withOwner: nil, options: nil)[0] as? UIView
  }
}
适用于Swift 3

您可以在UIView上创建扩展:

extension UIView {
    class func loadFromNibNamed(nibNamed: String, bundle: NSBundle? = nil) -> UIView? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
        ).instantiateWithOwner(nil, options: nil)[0] as? UIView
    }
}
注意:使用UINib更快,因为它为您提供缓存

然后你可以做:

ViewDetailItem.loadFromNibNamed("ViewBtnWishList")

您可以在任何视图上重复使用该方法。

这对我很有效

override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
    if self.subviews.count == 0 {
        return loadNib()
    }
    return self
}

private func loadNib() -> YourCustomView {
    return NSBundle.mainBundle().loadNibNamed("YourCustomViewNibName", owner: nil, options: nil)[0] as YourCustomView
}

在Xcode 7 beta 4和Swift 2.0中测试。 以下代码将xib分配给
UIView
。 您可以在故事板中使用此自定义xib视图,并访问
IBOutlet
对象

import UIKit

@IBDesignable class SimpleCustomView:UIView
{
    var view:UIView!;

    @IBOutlet weak var lblTitle: UILabel!

   @IBInspectable var lblTitleText : String?
        {
        get{
            return lblTitle.text;
        }
        set(lblTitleText)
        {
            lblTitle.text = lblTitleText!;
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        loadViewFromNib ()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        loadViewFromNib ()
    }
    func loadViewFromNib() {
        let bundle = NSBundle(forClass: self.dynamicType)
        let nib = UINib(nibName: "SimpleCustomView", bundle: bundle)
        let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
        view.frame = bounds
        view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        self.addSubview(view);



    }


}
以编程方式访问自定义视图

self.customView =  SimpleCustomView(frame: CGRectMake(100, 100, 200, 200))
        self.view.addSubview(self.customView!);

源代码-

您可以定义协议并将实现添加到协议扩展,而不是向UIView添加扩展。然后可以声明UIView符合协议

这允许返回类型为
Self
,而不是
UIView
。因此,调用方不必强制转换到类

解释如下:


我认为这是将xib分配给UIView的最简单也是最干净的方法。Xcode 7.3和swift 2.0

import UIKit

//Create CustomView class
class CustomView: UIView {

    class func instanceFromNib() -> UIView {
        return UINib(nibName: "CustomView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
    }
}

//Use it
let customView = CustomView.instanceFromNib() as! CustomView

只做了一个
UINib
扩展,从xib加载视图,并使用约束、泛型和强命名(不使用字符串,假设xib和实现的文件名相同)嵌入到容器视图中:


真正的Swift方法是使用协议和协议扩展

我这样使用它:首先,我创建一个协议

然后,我使用协议扩展对该协议进行默认实现

我们的协议的实施现在已经完成

为了使该协议生效,您需要我们的xib文件名,并且类是相同的。例如,例如

最后添加协议并使您的类“final”,如下所示

就这样

和使用


只需将这个简单类(swift 5)子类化即可:

正如其他人指出的,将文件的所有者设置为
CustomView
类(而不是xib的根视图本身)。然后将自定义类设置为
CustomView
,以替换为自定义视图类的任何视图。此外,autolayout尊重xib中的所有约束,至少作为UITableViewCell内容视图的子视图。对其他情况不太清楚



很简单,正如它碰巧发生的那样,不知何故,苹果为我们做了另一件追求这样一个基本的事情!多棒的公司啊!永远不会厌倦他们

使用
UINib
会更有效率。。。无论如何,
self
不能在Swift中分配。您可能想创建一个类方法,该方法使用xib文件初始化您的类。为什么要使用速度慢3-4倍的
NSBundle
加载nib?@holex我只是试图保持代码一致以解决实际问题,但我更新了它。谢谢,这样我就可以创建自定义uiview,如下所示??var customView=ViewDetailItem.loadFromNibNamed(“ViewBtnWishList”),但如果我想在创建自定义视图时初始化更多变量,该怎么办?在这种情况下,我们是否绕过了UIView的init方法?如果我在包含其他视图的布局中使用此方法,然后我将其导出到该类,我将由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[setValue:forUndefinedKey:]:此类不符合key infoView的键值编码要求。只是好奇-为什么要使用类func而不是静态func这是在故事板或xib文件中重用的最佳解决方案。如果您只是将加载的nib视图添加为子视图,则代理等属性无法正确设置请确保您是否有任何出口,是否将它们连接到XIB中的视图,而不是
文件所有者
,否则将出现KVO合规性错误。到目前为止,这是唯一适用于我的。谢谢无论如何,这是最合适的解决方案。我不知道为什么在我找到它之前这里只有10个投票。但不幸的是,当使用故事板时,这个解决方案实际上替换了故事板中最初的对象,这导致了视图约束或故事板完成的任何其他设置消失的情况。在其他XIB中也可以使用-这很好。但是,有一个问题,这不是直接从XIB创建自定义视图。它正在从XIB加载UIView,并将其作为子视图添加到自定义视图中。这是一个非常出色的贡献。非常清楚和完整。也感谢您将其发布到Github repo!一个小问题是
SimpleCustomView.swift中的成员变量“view”似乎是不必要的且未使用过的。一个来自许多解决方案,它不是静态方法的设置视图)完美答案。简洁,简洁,工作起来很有魅力。谢谢那么,我将把这段代码放在XIB的视图控制器中,还是放在我试图将XIB添加到的视图控制器中?@MarksCode,您需要将这段代码添加到
UIView
类的子集中;这与此上下文中的任何视图无关。请提供更多信息。“仅编码”和“尝试此”答案是错误的,因为它们不包含可搜索的内容,并且没有解释为什么有人应该“尝试此”。我们在这里努力成为知识的资源。我唯一要改变的是将
bundle
属性作为para移动到函数中
self.customView =  SimpleCustomView(frame: CGRectMake(100, 100, 200, 200))
        self.view.addSubview(self.customView!);
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
  }

}
import UIKit

//Create CustomView class
class CustomView: UIView {

    class func instanceFromNib() -> UIView {
        return UINib(nibName: "CustomView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
    }
}

//Use it
let customView = CustomView.instanceFromNib() as! CustomView
extension UINib {

    static func instantiateViewAndEmbedWithConstraints <T: UIView> (viewType viewType: T.Type, embedInto containerView: UIView) -> T {
        let view = UINib(nibName: String(viewType), bundle: nil).instantiateWithOwner(nil, options: nil).first as! T
        containerView.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: containerView, attribute: .Leading, multiplier: 1, constant: 0).active = true
        NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: containerView, attribute: .Trailing, multiplier: 1, constant: 0).active = true
        NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: containerView, attribute: .Top, multiplier: 1, constant: 0).active = true
        NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: containerView, attribute: .Bottom, multiplier: 1, constant: 0).active = true
        return view
    }

}
...outlets...
@IBOutlet var containerView: UIView!
var customView: CustomView!

...viewDidLoad...
customView = UINib.instantiateViewAndEmbedWithConstraints(viewType: CustomView.self, embedInto: containerView)
    protocol XibInitializable {
        static var name: String { get }
        static var bundle: Bundle? { get }

        static func fromXib() -> Self
    }
extension XibInitializable where Self : UIView {
    static var name: String {
        return String(describing: Self.self)
    }

    static var bundle: Bundle? {
        return nil
    }

    static func fromXib() -> Self {
        return UINib(nibName: name, bundle: bundle).instantiate(withOwner: nil, options: nil)[0] as! Self
    }
}
open class NibView: UIView {

    open override func awakeAfter(using coder: NSCoder) -> Any? {
        if subviews.count == 0 {
            return UINib(nibName: "\(Self.self)", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
        }
        return self
    }
}

class CustomView: NibView {
}