为什么在装入笔尖时使用此init方法会使对象超出范围? [英] Why does this init method when loading a nib return an object out of scope?
问题描述
为什么此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屋!