Bag*_*yer 140 xib uiview swift
这是我的Objective-C代码,我用它来为我的自定义加载一个笔尖UIView
:
-(id)init{
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"myXib" owner:self options:nil];
return [subviewArray objectAtIndex:0];
}
Run Code Online (Sandbox Code Playgroud)
Swift中的等效代码是什么?
Rob*_*son 287
我的贡献:
Swift 3/Swift 4
extension UIView {
class func fromNib<T: UIView>() -> T {
return Bundle(for: T.self).loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样称呼它:
let myCustomView: CustomView = UIView.fromNib()
Run Code Online (Sandbox Code Playgroud)
..甚至:
let myCustomView: CustomView = .fromNib()
Run Code Online (Sandbox Code Playgroud)
GK1*_*100 163
原始方案
.
class SomeView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("SomeView", owner: self, options: nil)
self.addSubview(self.view); // adding the top level view to the view hierarchy
}
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,这样我获得了一个从nib加载自身的类.然后,只要UIView可以在项目中使用(在界面生成器中或以编程方式),我就可以将SomeView用作类.
更新 - 使用Swift 3语法
在以下扩展中加载xib是作为实例方法编写的,然后可以像上面的初始化程序一样使用它:
extension UIView {
@discardableResult // 1
func fromNib<T : UIView>() -> T? { // 2
guard let contentView = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? T else { // 3
// xib not loaded, or its top view is of the wrong type
return nil
}
self.addSubview(contentView) // 4
contentView.translatesAutoresizingMaskIntoConstraints = false // 5
contentView.layoutAttachAll(to: self) // 6
return contentView // 7
}
}
Run Code Online (Sandbox Code Playgroud)
调用方法可能如下所示:
final class SomeView: UIView { // 1.
required init?(coder aDecoder: NSCoder) { // 2 - storyboard initializer
super.init(coder: aDecoder)
fromNib() // 5.
}
init() { // 3 - programmatic initializer
super.init(frame: CGRect.zero) // 4.
fromNib() // 6.
}
// other methods ...
}
Run Code Online (Sandbox Code Playgroud)
信用:在此解决方案中使用通用扩展程序的灵感来自Robert的答案.
编辑 将"视图"更改为"contentView"以避免混淆.还将数组下标更改为".first".
Log*_*gan 76
这是一个使用泛型UIView
从笔尖加载a的扩展
public extension UIView {
public class func fromNib(nibNameOrNil: String? = nil) -> Self {
return fromNib(nibNameOrNil, type: self)
}
public class func fromNib<T : UIView>(nibNameOrNil: String? = nil, type: T.Type) -> T {
let v: T? = fromNib(nibNameOrNil, type: T.self)
return v!
}
public class func fromNib<T : UIView>(nibNameOrNil: String? = nil, type: T.Type) -> T? {
var view: T?
let name: String
if let nibName = nibNameOrNil {
name = nibName
} else {
// Most nibs are demangled by practice, if not, just declare string explicitly
name = nibName
}
let nibViews = NSBundle.mainBundle().loadNibNamed(name, owner: nil, options: nil)
for v in nibViews {
if let tog = v as? T {
view = tog
}
}
return view
}
public class var nibName: String {
let name = "\(self)".componentsSeparatedByString(".").first ?? ""
return name
}
public class var nib: UINib? {
if let _ = NSBundle.mainBundle().pathForResource(nibName, ofType: "nib") {
return UINib(nibName: nibName, bundle: nil)
} else {
return nil
}
}
}
Run Code Online (Sandbox Code Playgroud)
我更喜欢这个,因为它不需要在笔尖中进行任何额外的设置.它基于通用命名约定,因此如果您的类是CustomView
,并且它匹配名为:的nib CustomView
,您可以这样做:
let myCustomView = CustomView.fromNib()
// or if you're unsure whether or not the nib exists
let myCustomView: CustomView? = CustomView.fromNib()
Run Code Online (Sandbox Code Playgroud)
如果您因任何原因需要具体了解nib名称,请传递一个字符串arg:
let myCustomView = MyCustomView.fromNib("non-conventional-name")
Run Code Online (Sandbox Code Playgroud)
已知的问题
使用私有视图类似乎会导致问题.这似乎是一个系统问题.
Jas*_*min 17
尝试以下代码.
var uiview :UIView?
self.uiview = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)[0] as? UIView
Run Code Online (Sandbox Code Playgroud)
编辑:
import UIKit
class TestObject: NSObject {
var uiview:UIView?
init() {
super.init()
self.uiview = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)[0] as? UIView
}
}
Run Code Online (Sandbox Code Playgroud)
Amr*_*fie 10
我通过以下代码用Swift实现了这一点:
class Dialog: UIView {
@IBOutlet var view:UIView!
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = UIScreen.mainScreen().bounds
NSBundle.mainBundle().loadNibNamed("Dialog", owner: self, options: nil)
self.view.frame = UIScreen.mainScreen().bounds
self.addSubview(self.view)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记将XIB 视图插座连接到swift中定义的视图插座.您还可以将First Responder设置为您的自定义类名称,以开始连接任何其他插座.
希望这可以帮助!
在Xcode 7 beta 4,Swift 2.0和iOS9 SDK中测试过.以下代码将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);
}
}
Run Code Online (Sandbox Code Playgroud)
以编程方式访问customview
self.customView = SimpleCustomView(frame: CGRectMake(100, 100, 200, 200))
self.view.addSubview(self.customView!);
Run Code Online (Sandbox Code Playgroud)
源代码 - https://github.com/karthikprabhuA/CustomXIBSwift
Swift 4协议扩展
public protocol NibInstantiatable {
static func nibName() -> String
}
extension NibInstantiatable {
static func nibName() -> String {
return String(describing: self)
}
}
extension NibInstantiatable where Self: UIView {
static func fromNib() -> Self {
let bundle = Bundle(for: self)
let nib = bundle.loadNibNamed(nibName(), owner: self, options: nil)
return nib!.first as! Self
}
}
Run Code Online (Sandbox Code Playgroud)
采用
class MyView: UIView, NibInstantiatable {
}
Run Code Online (Sandbox Code Playgroud)
此实现假定Nib与UIView类具有相同的名称。例如 MyView.xib。您可以通过在MyView中实现nibName()返回与默认协议扩展实现不同的名称来修改此行为。
在xib中,文件所有者是MyView,根视图类是MyView。
用法
let view = MyView.fromNib()
Run Code Online (Sandbox Code Playgroud)
我更喜欢这个解决方案(基于 @GK100 的答案):
在 SomeView.swift 中,我将 XIB 加载到init
或init:frame: CGRect
初始化程序中。不需要给“self”分配任何东西。一旦 XIB 加载,所有插座都会连接,包括顶层视图。唯一缺少的是将顶视图添加到视图层次结构中:
class SomeView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
NSBundle.mainBundle().loadNibNamed("SomeObject", owner: self, options: nil)
self.addSubview(self.view); // adding the top level view to the view hierarchy
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("SomeObject", owner: self, options: nil)
self.addSubview(self.view); // adding the top level view to the view hierarchy
}
...
}
Run Code Online (Sandbox Code Playgroud)如果项目中有很多自定义视图,则可以创建类 UIViewFromNib
斯威夫特2.3
class UIViewFromNib: UIView {
var contentView: UIView!
var nibName: String {
return String(self.dynamicType)
}
//MARK:
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
//MARK:
private func loadViewFromNib() {
contentView = NSBundle.mainBundle().loadNibNamed(nibName, owner: self, options: nil)[0] as! UIView
contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
contentView.frame = bounds
addSubview(contentView)
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特3
class UIViewFromNib: UIView {
var contentView: UIView!
var nibName: String {
return String(describing: type(of: self))
}
//MARK:
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
//MARK:
func loadViewFromNib() {
contentView = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?[0] as! UIView
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentView.frame = bounds
addSubview(contentView)
}
}
Run Code Online (Sandbox Code Playgroud)
并且在每个继承的类中UIViewFromNib
,nibName
如果.xib
文件具有不同的名称,您也可以覆盖属性:
class MyCustomClass: UIViewFromNib {
}
Run Code Online (Sandbox Code Playgroud)
建立在上述解决方案之上.
这将适用于所有项目包,并且在调用fromNib()时不需要泛型.
斯威夫特2
extension UIView {
public class func fromNib() -> Self {
return fromNib(nil)
}
public class func fromNib(nibName: String?) -> Self {
func fromNibHelper<T where T : UIView>(nibName: String?) -> T {
let bundle = NSBundle(forClass: T.self)
let name = nibName ?? String(T.self)
return bundle.loadNibNamed(name, owner: nil, options: nil)?.first as? T ?? T()
}
return fromNibHelper(nibName)
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特3
extension UIView {
public class func fromNib() -> Self {
return fromNib(nibName: nil)
}
public class func fromNib(nibName: String?) -> Self {
func fromNibHelper<T>(nibName: String?) -> T where T : UIView {
let bundle = Bundle(for: T.self)
let name = nibName ?? String(describing: T.self)
return bundle.loadNibNamed(name, owner: nil, options: nil)?.first as? T ?? T()
}
return fromNibHelper(nibName: nibName)
}
}
Run Code Online (Sandbox Code Playgroud)
可以像这样使用:
let someView = SomeView.fromNib()
Run Code Online (Sandbox Code Playgroud)
或者像这样:
let someView = SomeView.fromNib("SomeOtherNibFileName")
Run Code Online (Sandbox Code Playgroud)
Swift 5
某处定义如下:
extension UIView {
public class func fromNib<T: UIView>() -> T {
let name = String(describing: Self.self);
guard let nib = Bundle(for: Self.self).loadNibNamed(
name, owner: nil, options: nil)
else {
fatalError("Missing nib-file named: \(name)")
}
return nib.first as! T
}
}
Run Code Online (Sandbox Code Playgroud)
并像上面一样使用:
let view: MyCustomView = .fromNib();
Run Code Online (Sandbox Code Playgroud)
它将在与 相同的包中搜索
MyCustomView
,然后加载MyCustomView.nib
文件(如果文件存在,并且添加到项目中)。
斯威夫特 4
不要忘记写“.first as?CustomView”。
if let customView = Bundle.main.loadNibNamed("myXib", owner: self, options: nil)?.first as? CustomView {
self.view.addSubview(customView)
}
Run Code Online (Sandbox Code Playgroud)
如果你想在任何地方使用
最佳解决方案是Robert Gummesson的回答。
extension UIView {
class func fromNib<T: UIView>() -> T {
return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样调用它:
let myCustomView: CustomView = UIView.fromNib()
Run Code Online (Sandbox Code Playgroud)
let subviewArray = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)
return subviewArray[0]
Run Code Online (Sandbox Code Playgroud)
使用Swift执行此操作的一个好方法是使用枚举.
enum Views: String {
case view1 = "View1" // Change View1 to be the name of your nib
case view2 = "View2" // Change View2 to be the name of another nib
func getView() -> UIView? {
return NSBundle.mainBundle().loadNibNamed(self.rawValue, owner: nil, options: nil).first as? UIView
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的代码中,您可以简单地使用:
let view = Views.view1.getView()
Run Code Online (Sandbox Code Playgroud)
我只是这样做:
if let myView = UINib.init(nibName: "MyView", bundle: nil).instantiate(withOwner: self)[0] as? MyView {
// Do something with myView
}
Run Code Online (Sandbox Code Playgroud)
此示例使用主包中笔尖“MyView.xib”中的第一个视图。但您可以更改索引、笔尖名称或捆绑包(默认为 main )。
我曾经将视图唤醒到视图初始化方法中,或者按照上面建议的答案创建通用方法(顺便说一下,这很聪明),但我不再这样做了,因为我注意到用例通常是不同的,并且要涵盖在所有情况下,通用方法都变得与使用 UINib.instantiate 方法一样复杂。
我更喜欢使用工厂对象,通常是使用视图的 ViewController,或者如果需要在多个地方使用视图,则使用专用工厂对象或视图扩展。
在此示例中,ViewController 从 nib 加载视图。可以更改 nib 文件以对同一视图类使用不同的布局。(这不是很好的代码,它只是说明了这个想法)
class MyViewController {
// Use "MyView-Compact" for compact version
var myViewNibFileName = "MyView-Standard"
lazy var myView: MyView = {
// Be sure the Nib is correct, or it will crash
// We don't want to continue with a wrong view anyway, so ! is ok
UINib.init(nibName: myViewNibFileName, bundle: nil).instantiate(withOwner: self)[0] as! MyView
}()
}
Run Code Online (Sandbox Code Playgroud)
//
// Refactored by Essam Mohamed Fahmi.
//
import UIKit
extension UIView
{
static var nib: UINib
{
return UINib(nibName: "\(self)", bundle: nil)
}
static func instantiateFromNib() -> Self?
{
return nib.instantiate() as? Self
}
}
extension UINib
{
func instantiate() -> Any?
{
return instantiate(withOwner: nil, options: nil).first
}
}
Run Code Online (Sandbox Code Playgroud)
let myCustomView: CustomView = .instantiateFromNib()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
165470 次 |
最近记录: |