在Swift中,与loadNibNamed相当的方法是什么?

23
我正在将我的Objective-C代码转换为Swift,并想知道这段代码在Swift中的等效写法。
[[[NSBundle mainBundle] loadNibNamed:@"Games-New" owner:nil  
options:nil] firstObject]; 

谢谢。


3
不要过多纠结于具体方法——它们都遵循同样的转换规则。如果你正在将代码转换为 Swift,应该熟悉如何从 Swift 调用 Objective-C 方法。参考链接:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html。 - Caleb
10个回答

34

可能API已更改。 loadNibNamed 的第三个参数不再是options,而是topLevelObjects。以下代码适用于我:

var objects: NSArray?
NSBundle.mainBundle().loadNibNamed("MyView", owner: self, topLevelObjects: &objects)

4
对于OS X 10.10来说,这个答案比目前接受的答案更正确。 - ybakos
就我个人而言,当我尝试这样做时,会出现以下语法错误:value of optional type 'NSArray?' not unwrapped; did you mean to use '!' or '?'?。与其将“objects”声明为可选值,似乎更应该使用空的NSArray()进行初始化。 - Chris Frederick

19
Bundle.main.loadNibNamed("Games-New", owner: nil, options: nil)[0]

1
这给了我一个“'Bool'没有名为'subscript'的成员”的编译错误。 - speg
4
对于我来说,Xcode 6 Beta 5 提醒了我有关“选项”的问题,它指出应该是“topLevelObjects”。 - Peter
1
你需要进行类型转换,loadNibNamed返回的是[AnyObject]。var awesomeView = NSBundle.mainBundle().loadNibNamed("Games-New", owner: nil, options: nil)[0] as? AwesomeView - aryaxt
我不知道之前的版本,但在Swift 2中它看起来像这样:let cell: UITableViewCell = NSBundle.mainBundle().loadNibNamed(cellIdentifier, owner:self, options: nil)[0] as! UITableViewCell - Jay Imerman
1
NSBundle.mainBundle().loadNibNamed("Games-New", owner: nil, options: nil).firstObject请勿硬编码。 - Abhishek Bedi
显示剩余4条评论

16

这里是一个UIView扩展

public extension UIView {

    public class func instantiateFromNib<T: UIView>(viewType: T.Type) -> T {
        return NSBundle.mainBundle().loadNibNamed(String(describing: viewType), owner: nil, options: nil)?.first as! T
    }

    public class func instantiateFromNib() -> Self {
        return instantiateFromNib(self)
    }

}

使用方法

let awesomeView = AwesomeView.instantiateFromNib()

或者

let awesomeView = UIView.instantiateFromNib(AwesomeView.self)

这导致我的程序崩溃。 - Umair Aamir
你是不是漏掉了一些可选项?NSBundle.mainBundle().loadNibNamed(String(viewType), owner: nil, options: nil).first as? T, func instantiateFromNib<T: UIView>(viewType: T.Type) -> T?, public class func instantiateFromNib() -> Self? - Hugues BR
@HuguesBR 我不明白为什么它应该使用可选项。 - aryaxt
@aryaxt 或者强制解包,你已经添加了 :) - Hugues BR
哦,我明白了,当时Swift 1.0版本支持使用as :) - aryaxt
我们为什么要使用.first呢?这样做有什么必要吗?难道nib文件中不仅仅包含视图吗? - mfaani

7

Swift 3


名称
nib 文件的名称,不需要包含 .nib 扩展名。

所有者
分配为 nib 的“文件所有者”对象的对象。

选项
包含在打开 nib 文件时使用的选项的字典。

第一个视图
如果您没有定义第一个视图,则会获取所有视图。因此,您需要在其中获取一个视图并设置first

Bundle.main.loadNibNamed("yourUIView", owner: self, options: nil)?.first as! yourUIView

1
你是指它会抓取所有的视图吗?怎么可能有多个视图?!我只需要从storyboard中拖出一个视图,然后再在里面放置标签/图片就好了。或者这是否意味着我可以拖动多个类似容器的视图,而我所拖出的第一个视图会是第一个之类的?这将是一个非常糟糕的想法,因为我拖出的第一个是哪个...虽然我怀疑那不是它的意思... - mfaani
如果我有一个或多个视图,那么抓取所有视图,所以我需要成为第一个加载的视图。这样会更加清晰。 - Nazmul Hasan

6
使用此代码来加载您的nib文件。
let myView = NSBundle.mainBundle().loadNibNamed("MyView", owner: nil, options: nil)[0] as UIView

然后您可以像平常一样将它添加到您的视图中。
view.addSubview(myView)

'NSBundle'已更名为'Bundle'。请更新您的代码块。 让myView = Bundle.main.loadNibNamed("MyDenizbankLoading", owner: nil, options: nil)![0] as!UIView - Emre Gürses

3
在文档中,看起来对于 macOSiOS 是不同的。
对于 macOSSwift 4,以下内容适用于我:
func loadFromNib(_ nibName: String) -> NSView? {
    var topLevelObjects: NSArray?
    if Bundle.main.loadNibNamed(NSNib.Name(rawValue: nibName), owner: self, topLevelObjects: &topLevelObjects) {
        return topLevelObjects?.first(where: { $0 is NSView } ) as? NSView
    } else {
        return nil
    }
}

3

对于Swift 3:

Bundle.main.loadNibNamed("Games-New", owner: nil, options: nil)?[0]

FYI:NS在Swift 3中已经(并非完全)被移除


2
在Swift 4中,NSBundle.mainBundle被更改为Bundle.main.loadNibNamed
Bundle.main.loadNibNamed("MyDenizbankLoading", owner: nil, options: nil)![0]

0

这对我有用

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    var objects: NSArray?
    Bundle.main.loadNibNamed("CellView", owner: self, topLevelObjects: &objects)

    var newView = NSView()
    for object in objects ?? [] {
        if (object is NSView) {
            newView = object as! NSView
            break;
        }
    }

    var cellView: CellView?
    for view in newView.subviews {
        print("class: \(view.className) ")
        if (view is CellView) {
            cellView = view as? CellView
            break;
        }
    }

    cellView?.imageView.image = image
    cellView?.textFieldView.stringValue = text

    return cellView
}

-1

这是在Swift 4中如何在macOS上执行的方式

注册

collectionView.register(NSNib(nibNamed: NSNib.Name(rawValue: "Cell"), bundle: nil)!,
                            forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"))

出队

func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {

  let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"), for: indexPath)
  guard let cell = item as? Cell else { return item }

  let value = values[(indexPath as NSIndexPath).item]
  cell.imageView?.setImage(url: value, placeholder: Image(named: NSImage.Name(rawValue: "placeholder")))

  return cell
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接