为什么在装入笔尖时使用此init方法会使对象超出范围? [英] Why does this init method when loading a nib return an object out of scope?

查看:83
本文介绍了为什么在装入笔尖时使用此init方法会使对象超出范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么此init方法会返回超出范围的对象?

Why does this init method return an object out of scope?

使用XCode 4.2、4.3的基本SDK和ARC,我试图从笔尖(不是UIViewController)加载UIView.在此过程中,我根本不需要使用UIViewController.

Using XCode 4.2, base SDK of 4.3, and ARC, I'm trying to load an UIView from a nib (not a UIViewController). I need to not use a UIViewController at all in the process.

在阅读此答复后的S.O.问题在这里,看起来可以完成: 如何加载使用通过Interface Builder创建的nib文件创建UIView (用户"MusiGenesis"的回答描述了该过程)

After reading this answer to an S.O. question here, it looks like it can be done: How to load a UIView using a nib file created with Interface Builder (The answer by user "MusiGenesis" describes the process)

我创建了一个带有单个标签的UIView子类:

I created a sub-class of UIView with a single label:

@interface MyView : UIView
@property (unsafe_unretained, nonatomic) IBOutlet UILabel *textLabel;
@end

在实现中,我重写了initWithFrame:

In the implementation I override initWithFrame:

- (id)initWithFrame:(CGRect)frame
{
    //self = [super initWithFrame:frame];
    self = [JVUIKitUtils initWithNibName:@"MyView" withOwner:self];
    if( self )
    {
        NSLog(@"Created");
    }
    return self;
}

在I.B.我用一个视图创建了一个名为"MyView.xib"的文件.它具有一个标签作为子视图,我通过将其拖动到h文件中来创建了label属性.

In I.B. I created a file named "MyView.xib" with a single view. It has a label as a sub-view, and I created the label property by dragging it to the h file.

在另一个文件中,我创建了这个可重复使用的静态方法:

And in another file, I created this re-usable static method:

+ (id)initWithNibName:(NSString*)nibName withOwner:(id)uiView
{
    id object = nil;
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:uiView options:nil]; // 1 object, out of scope
    for( id tempObject in bundle)
    {
        if( [tempObject isKindOfClass:[uiView class]] ) object = tempObject;
        break;
    }
    return object;
}

如下面的屏幕快照所示,该捆绑包具有一个对象引用,但超出了范围.

As you can see in the following screen shot, the bundle has one object reference, but it's out of scope.

并调试:

这是我的实例化代码:

subView = [[MyView alloc] initWithFrame:CGRectZero]; // ok
NSAssert(subView != nil, @"MyView was nil"); // fail

关于为什么其他S.O.的任何想法张贴者能够使它正常工作,但这不是吗?

Any ideas on why the other S.O. poster was able to get it to work but this does not?

推荐答案

在加载笔尖的过程中,所有者的使用似乎有些混乱.看来您试图同时使用该视图作为笔尖的所有者和其中的第一个对象.

The use of the owner seems a bit confusing in the way that you are loading a nib. It appears that you are trying to use the view as both the owner of the nib and the first object in it.

您是要从笔尖加载MyView(即您的笔尖文件中的视图类定义为MyView)还是要从笔尖加载MyView的子视图?

Are you trying to load MyView from your nib (i.e. is the class of the view inside your nib files defined as MyView) or are you trying to load a subview of MyView from the nib?

如果笔尖内的视图是MyView,请按以下步骤进行加载.创建此静态方法作为UIView上的类别:

If the view inside your nib is a MyView, here's how to load it. Create this static method as a category on UIView:

@implementation UIView (NibLoading)

+ (id)viewWithNibName:(NSString*)nibName
{
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:nil options:nil];
    if ([bundle count])
    {
        UIView *view = [bundle objectAtIndex:0];
        if ([view isKindOfClass:self])
        {
            return view;
        }
        NSLog(@"The object in the nib %@ is a %@, not a %@", nibName, [view class], self);
    }
    return nil;
}

@end

这将使您可以从笔尖文件中加载任何类型的视图(该视图必须是笔尖中定义的第一项).您将这样创建视图:

That will let you load any kind of view from a nib file (the view needs to be the first item defined in the nib). You would create your view like this:

MyView *view = [MyView viewWithNibName:@"MyView"];

如果笔尖内部的视图不是MyView,但是您希望将其作为MyView的子视图加载,并且MyView被定义为笔尖文件中文件的所有者,请执行以下操作:

If the view inside the nib is not a MyView, but you want to load it as a subview of MyView, with MyView defined as the file's owner in the nib file, do it like this:

@implementation UIView (NibLoading)

- (void)loadContentsFromNibName:(NSString*)nibName
{
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
    if ([bundle count])
    {
        UIView *view = [bundle objectAtIndex:0];
        if ([view isKindOfClass:[UIView class]])
        {
            //resize view to fit
            view.frame = self.bounds;

            //add as subview
            [self addSubview:view];
        }
        NSLog(@"The object in the nib %@ is a %@, not a UIView", nibName, [view class]);
    }
}

@end

使用该方法,只需使用initWithFrame正常创建视图,然后调用loadContentsFromNibName从笔尖中擦除内容.您将这样加载视图:

Using that approach, just create your view as normal using initWithFrame, then call loadContentsFromNibName to loa the contents from a nib. You would load your view like this:

MyView *view = [[MyView alloc] initWithFrame:CGRect(0,0,100,100)];
[view loadContentsFromNibName:@"MyView"];

这篇关于为什么在装入笔尖时使用此init方法会使对象超出范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆