Bil*_*ner 5 macos appkit swift3 macos-sierra xcode8
我已经看过很多关于如何在Interface Builder中创建自定义视图的教程.一切都适用于iOS,但MacOS应该相似,不是吗?我尝试了一些方法但没有一个完全成功.该init(coder:)呼叫的NIB实例化(通过Bundle.main.loadNibNamed或NSNib,反过来,调用init(coder:)与无限递归结束了,如果我类我笔尖的主要观点为我的自定义类
如果我使用标准类,那么使文件的所有者我的自定义类工作得更好,但仍然是不对的.
是否有一个使用AppKit创建自定义控件的示例?我最接近的是显示自定义控件但没有自动布局设置有效.
它必须相当简单,但我还没想出来.
这是我到目前为止:
import Cocoa
@IBDesignable
class MyControl: NSView {
@IBOutlet var customView: NSView! // The top level NSView
@IBOutlet weak var insideButton: NSButton! // The button inside the view
let myName: String
required init?(coder: NSCoder) {
super.init(coder: coder)
if Bundle.main.loadNibNamed("MyControl", owner: self, topLevelObjects: nil) {
addSubview(customView)
}
}
Run Code Online (Sandbox Code Playgroud)
}
基于NSView的nib包含一个居中的NSButton.的File's Owner类设置为MyControl,顶层视图保持为NSView
的Main.storyboard已定制视图归类为MyControl具有的高度和宽度设定为中心.
当我查看Main.storyboard它有自定义视图的框架但它是空白.
当我运行应用程序时,显示的窗口是空白的.
Bil*_*ner 11
经过Apple Support的大量搜索和大量帮助,我发现在AppKit中创建和使用自定义控件非常容易.只是它就像锁中的钥匙一样,除非你做对了,否则你根本不会得到太多.
我创建了一个示例项目并将其发布到GitHub:https://github.com/ctgreybeard/SwiftCustomControl
这是一个小项目,我希望我已经完全评论它,以便其他人可以理解它.
这个过程的要点是这样的:
File's Owner新类的名称.required init?(coder: coder)let newNib = NSNib(nibNamed: myName, bundle: Bundle(for: type(of: self)))其中MYNAME是厦门国际银行的名称.newNib.instantiate(withOwner: self, topLevelObjects: nil) 新的NSNibself.在constraints属性的for循环中执行此操作.或者,您可以简单地创建您知道的约束.self.addSubview对于所有旧的顶级,subviews这很容易subviews在旧NSView中的数组的for循环中完成.您已完成...现在,自定义控件应该在Interface Builder和应用程序中正确显示.
评论:这很简单,实际上不应该是必要的.我应该能够在XIB中的顶级NSView中使用我的自定义类名,并完成它.init中的代码只是用我们的自定义视图替换顶级NSView.
以下是Bills解决方案的一些代码:
我们可以创建一个协议LoadableNib以使我们的自定义视图符合要求,并在满足以下条件时对其进行扩展以获取此功能:
protocol LoadableNib {
var contentView: NSView! { get }
}
extension LoadableNib where Self: NSView {
func loadViewFromNib() {
let bundle = Bundle(for: type(of: self))
let nib = NSNib(nibNamed: .init(String(describing: type(of: self))), bundle: bundle)!
_ = nib.instantiate(withOwner: self, topLevelObjects: nil)
let contentConstraints = contentView.constraints
contentView.subviews.forEach({ addSubview($0) })
for constraint in contentConstraints {
let firstItem = (constraint.firstItem as? NSView == contentView) ? self : constraint.firstItem
let secondItem = (constraint.secondItem as? NSView == contentView) ? self : constraint.secondItem
addConstraint(NSLayoutConstraint(item: firstItem as Any, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在我们的自定义视图类中:
class YourViewClass: NSView, LoadableNib {
@IBOutlet var contentView: NSView!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记按照Bill的回答(您的自定义视图类的File Owner的类,以及NSView用于容纳视图内容并连接到contentView插座的容器)设置xib 。
| 归档时间: |
|
| 查看次数: |
3872 次 |
| 最近记录: |