正确的加载UIView子类的Nib的方法

Ada*_*ite 98 iphone objective-c xib uiview ios

我知道之前已经问过这个问题,但答案是矛盾的,我很困惑,所以请不要激怒我.

我希望UIView在我的应用程序中有一个可重用的子类.我想用nib文件描述接口.

现在让我们说它是一个加载指示器视图,其中包含一个活动指示器.我希望在某个事件上实例化此视图并激活到视图控制器的视图.我可以用编程方式描述视图的界面没有问题,以编程方式创建元素并在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;
    }
Run Code Online (Sandbox Code Playgroud)

但是我覆盖了自己,当我实例化它时:

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

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

我必须手动设置框架而不是从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) {
                        }];
Run Code Online (Sandbox Code Playgroud)

正确的做法仍然需要

是否应该使用视图控制器和带有nib名称的init完成?我应该在代码中的某些UIView初始化方法中设置nib吗?或者我做得好吗?

小智 131

MyViewClass *myViewObject = [[[NSBundle mainBundle] loadNibNamed:@"MyViewClassNib" owner:self options:nil] objectAtIndex:0]
Run Code Online (Sandbox Code Playgroud)

我正在使用它初始化我可重用的自定义视图.


请注意,您可以在那里使用"firstObject",它更清洁一点."firstObject"是NSArray和NSMutableArray的一个方便方法.

这是加载xib以用作表头的典型示例.在你的文件YourClass.m中

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

通常,在TopArea.xib,您将单击文件所有者并将文件所有者设置为YourClass.然后实际上在YourClass.h中你将拥有IBOutlet属性.在TopArea.xib,您可以将控件拖动到这些插座.

不要忘记TopArea.xib,你可能需要点击View本身并将其拖到某个插座,这样你就可以控制它了.(一个非常有价值的提示是,当您为表格单元格行执行此操作时,您必须这样做 - 您必须将视图本身连接到代码中的相关属性.)


Ans*_*Ans 39

如果您想保持自己CustomViewxib独立性File's Owner,请按照以下步骤操作

  • 将该File's Owner字段留空.
  • 单击xib您的文件中的实际视图CustomView并将其设置Custom ClassCustomView(自定义视图类的名称)
  • 添加IBOutlet.h您的自定义视图的文件.
  • .xib自定义视图的文件中,单击视图然后进入Connection Inspector.在这里,您将在.h文件中定义所有IBOutlet
  • 将它们与各自的视图连接起来.

.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;
}
Run Code Online (Sandbox Code Playgroud)

现在,当您要加载时CustomView,请使用以下代码行 [[CustomView alloc] init];


iph*_*nic 24

请执行以下步骤

  1. 创建一个名为MyView .h/.m类的类UIView.
  2. 创建一个同名的xib MyView.xib.
  3. 现在更改文件所有者类UIViewController来自NSObject于厦门国际银行.见下图 在此输入图像描述
  4. 将文件所有者视图连接到您的视图.见下图 在此输入图像描述

  5. 将视图的类更改为MyView.与3相同.

  6. 场所控件创建IBOutlets.

以下是加载View的代码:

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

希望能帮助到你.

澄清:

UIViewController用于加载你的xib以及你在MyView xib中UIViewController实际MyView分配的视图.

演示在这里做了一个演示

  • 在您的xib文件中忽略文件所有者.然后你可以通过只做一个MyView*view = [[UINib instantiateWithOwner:nil options:nil] lastObject]来避免创建一个UIViewController; (2认同)

Ada*_*ite 10

大约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()
Run Code Online (Sandbox Code Playgroud)


vka*_*lit 8

在Swift中:

例如,您的自定义类的名称是 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
}
Run Code Online (Sandbox Code Playgroud)

然后设置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)
}
Run Code Online (Sandbox Code Playgroud)