正确的方式来加载笔尖的UIView子类(Correct way to load a Nib for

2019-07-21 14:43发布

我知道这个问题已经被问过,但答案是矛盾的,我很困惑,所以请不要火焰我。

我想有一个可重复使用UIView在我的应用程序的子类。 我想用笔尖文件来描述接口。

现在,让我们说这是在它的活动指示灯负载指示灯视图。 我想一些事件来实例化这个视图和动画中的视图控制器的看法。 我可以描述视图的界面上没有问题编程,编程方式创建的元素和设置的init方法内它们的帧等

我怎样才能做到这一点使用笔尖有关系吗? 保持在界面生成器给定的尺寸,而无需设置一个帧。

我已经成功地做到这样,但我敢肯定,这是错误的(它只是一个与它一选择器视图):

 - (id)initWithDataSource:(NSDictionary *)dataSource {
        self = [super init];
        if (self){
            self = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@", [self class]] owner:self options:nil] objectAtIndex:0];
            self.pickerViewData = dataSource;
            [self configurePickerView];
        }
        return self;
    }

但我改写自己,当我实例吧:

FSASelectView *selectView = [[FSASelectView alloc] initWithDataSource:selectViewDictionary];
    selectView.delegate = self;

    selectView.frame = CGRectMake(0, self.view.bottom + 50, [FSASelectView width], [FSASelectView height]);

我必须手动设置帧,而不是把它从IB回升。

编辑:我想创建一个视图控制器这个自定义视图,并有机会获得控制视图的元素。 我不想要一个新的视图控制器。

谢谢

编辑:我不知道这是不是最好的做法,我敢肯定,它不是,但是这是我做到了:

FSASelectView *selectView = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@",[FSASelectView class]] owner:self options:nil] objectAtIndex:0];
    selectView.delegate = self;
    [selectView configurePickerViewWithData:ds];
    selectView.frame = CGRectMake(0, self.view.bottom + 50, selectView.width, selectView.height);
    selectView.alpha = 0.9;
    [self.view addSubview:selectView];
    [UIView animateWithDuration: 0.25 delay: 0 options:UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveEaseInOut animations:^{
                            selectView.frame = CGRectMake(0, self.view.bottom - selectView.height, selectView.width, selectView.height);
                            selectView.alpha = 1;
                        } completion:^(BOOL finished) {
                        }];

正确的做法仍想

如果这种已经使用视图控制器和init用笔尖的名字呢? 如果我已在代码中的一些的UIView初始化方法笔尖? 或者是我做了什么不好?

Answer 1:

MyViewClass *myViewObject = [[[NSBundle mainBundle] loadNibNamed:@"MyViewClassNib" owner:self options:nil] objectAtIndex:0]

我使用这个初始化我有可重复使用的自定义视图。


请注意,您可以在年底有使用“firstObject”,这是一个有点清洁。 “firstObject”是的NSArray和NSMutableArray的一个方便的方法。

下面是加载厦门国际银行的表头使用的一个典型的例子。 在您的文件YourClass.m

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return [[NSBundle mainBundle] loadNibNamed:@"TopArea" owner:self options:nil].firstObject;
}

通常,在TopArea.xib ,您可以点击文件所有者,并设置文件所有者YourClass。 然后居然在YourClass.h你将有IBOutlet中的属性。 在TopArea.xib ,你可以拖动控制到这些插座。

不要忘记,在TopArea.xib ,您可能需要点击查看本身并拖动到一些插座,所以你必须控制它,如果需要的话。 (一款非常值得提示的是,当你这样做的表格单元格行,你绝对要做到这一点 - 你必须连接视图本身在你的代码中的相关属性)



Answer 2:

如果你想保持你的CustomViewxib独立的File's Owner ,那么请按照下列步骤

  • 保留File's Owner字段为空。
  • 在点击实际视图xib的文件CustomView并设置其Custom ClassCustomView (自定义视图类的名称)
  • 添加IBOutlet.h您的自定义视图的文件。
  • .xib您的自定义视图的文件,点击查看,并去Connection Inspector 。 在这里,您将您的所有IBOutlets您在定义.h文件
  • 各自的观点将它们连接起来。

.m您的文件CustomView类,重写init方法如下

-(CustomView *) init{
    CustomView *result = nil;
    NSArray* elements = [[NSBundle mainBundle] loadNibNamed: NSStringFromClass([self class]) owner:self options: nil];
    for (id anObject in elements)
    {
        if ([anObject isKindOfClass:[self class]])
        {
            result = anObject;
            break;
        }
    }
    return result;
}

现在,当你想加载CustomView ,使用下面的代码行[[CustomView alloc] init];



Answer 3:

按照下面的步骤

  1. 创建一个名为类型的MyView的.H / .M类UIView
  2. 创建一个同名的厦门国际银行MyView.xib
  3. 现在更改文件所有者类UIViewControllerNSObject在厦门国际银行。 见下图
  4. 连接文件所有者查看您的视图。 见下图

  5. 更改类视图以的MyView 。 同3。

  6. 将控件创建IBOutlets。

下面是加载查看的代码:

UIViewController *controller=[[UIViewController alloc] initWithNibName:@"MyView" bundle:nil];
MyView* view=(MyView*)controller.view;
[self.view addSubview:myview];

希望能帮助到你。

澄清

UIViewController用来加载你的厦门国际银行和该视图UIViewController实际上已经是MyView ,你在厦门国际银行MyView的已指定..

演示我做了一个演示抢在这里



Answer 4:

回答我的问题约2或某物年后在这里,但...

它采用了协议扩展,所以你可以不用对所有类的任何额外的代码。

/*

Prerequisites
-------------
- In IB set the view's class to the type hook up any IBOutlets
- In IB ensure the file's owner is blank

*/

public protocol CreatedFromNib {
    static func createFromNib() -> Self?
    static func nibName() -> String?
}

extension UIView: CreatedFromNib { }

public extension CreatedFromNib where Self: UIView {

    public static func createFromNib() -> Self? {
        guard let nibName = nibName() else { return nil }
        guard let view = NSBundle.mainBundle().loadNibNamed(nibName, owner: nil, options: nil).last as? Self else { return nil }
        return view
    }

    public static func nibName() -> String? {
        guard let n = NSStringFromClass(Self.self).componentsSeparatedByString(".").last else { return nil }
        return n
    }
}

// Usage:
let myView = MyView().createFromNib()


Answer 5:

在斯威夫特:

例如,你的自定义类的名字是InfoView

起初,你创建的文件InfoView.xibInfoView.swift是这样的:

import Foundation
import UIKit

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

然后设置File's OwnerUIViewController是这样的:

您重命名ViewInfoView

右键单击File's Owner和你的连接view现场与您InfoView

确保类名称为InfoView

而在此之后,你可以在你的自定义类的添加操作按钮,没有任何问题:

而在你这个自定义类的用法MainViewController

func someMethod() {
    var v = InfoView.instanceFromNib()
    v.frame = self.view.bounds
    self.view.addSubview(v)
}


Answer 6:

那么你既可以使用初始化视图控制器的厦门国际银行,并使用viewController.view。 还是去做了,你所采取的方式。 只有做出UIView子类作为控制器UIView是一个坏主意。

如果你没有任何的出口从您的自定义视图,那么你可以直接使用UIViewController类进行初始化。

更新:在您的情况:

UIViewController *genericViewCon = [[UIViewController alloc] initWithNibName:@"CustomView"];
//Assuming you have a reference for the activity indicator in your custom view class
CustomView *myView = (CustomView *)genericViewCon.view;
[parentView addSubview:myView];
//And when necessary
[myView.activityIndicator startAnimating]; //or stop

否则,你必须做出一个自定义UIViewController (使它作为文件的所有者,从而使得出口被正确连接好)。

YourCustomController *yCustCon = [[YourCustomController alloc] initWithNibName:@"YourXibName"].

无论你想添加就可以使用视图。

[parentView addSubview:yCustCon.view];

然而经过另一个视图控制器(已被用于另一个视图)作为业主,而加载厦门国际银行是不是一个好主意,因为控制器的视图属性将被改变,当你要访问原始视图,你不会有对它的引用。

编辑:如果你有你的设置与为同一主文件的所有者新XIB你将面对这个问题UIViewController类,并追平了视图属性设置为新厦门国际银行视图。

即;

  • YourMainViewController - 管理 - MAINVIEW
  • CustomView - 需要有需要时从厦门国际银行加载。

下面的代码会造成混乱以后,如果你写的看法做了负载物内部YourMainViewController 。 这是因为self.view从这个角度上会参考您的customview

-(void)viewDidLoad:(){
  UIView *childView= [[[NSBundle mainBundle] loadNibNamed:@"YourXibName" owner:self options:nil] objectAtIndex:0];
}


文章来源: Correct way to load a Nib for a UIView subclass