从nib文件加载UIView而不需要猜测 [英] Loading UIView from a nib file without guesswork

查看:103
本文介绍了从nib文件加载UIView而不需要猜测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这是另一个问题。



我正在创建一个名为 ProgressView 的UIView,这是一个半透明的查看活动指示器和进度条。



我希望能够在我的应用程序中的不同视图控制器中使用此视图。



我知道有3种不同的方法(但我只对其中一种感兴趣):



1)以编程方式创建整个视图,根据需要进行实例化和配置。不用担心我得到那个。



2)在界面构建器中创建UIView,添加所需的对象并使用如下方法加载它。问题在于我们基本上猜测视图是objectAtIndex:0,因为在文档中我没有找到对从 [[NSBundle mainBundle] loadNibName:[[NSBundle mainBundle] loadNibName: function。

  NSArray * nibContents = [[NSBundle mainBundle] loadNibNamed:@yournib
所有者:self
选项:nil];
UIView * myView = [nibContents objectAtIndex:0];
myView.frame = CGRectMake(0,0,300,400); //或者你需要的任何坐标
[scrollview addSubview:myView];

3)子类UIViewController让它按照正常情况管理视图。在这种情况下,我永远不会实际将视图控制器推送到堆栈上,而只是将其推送到主视图:

  ProgressViewController * vc = [[ProgressViewController alloc] initWithNibName:@ProgressViewbundle:nil]; 
[vc.view setCenter:CGPointMake(self.view.center.x,self.view.center.y)];
[self.view addSubview:vc.view];
[vc release];

据我所知,#3是正确的做法(除了编程之外) )但我不完全确定释放ProgressView的视图控制器是否安全,而另一个控制器的视图保留其主视图(直觉觉得它会泄漏?)?



在这种情况下,我应该在内存管理方面做些什么,我应该在何时何地发布ProgressView的视图控制器?



提前感谢您的想法。



干杯,



Rog

解决方案

我认为您的解决方案#3通过引入UIViewController实例作为ProgressView的容器来增加不必要的复杂性,以便您可以设置nib绑定。虽然我认为能够使用IBOutlet绑定属性而不是遍历nib内容是很好的,但您可以这样做,而无需引入您既不需要也不想要的行为的UIViewController。这应避免您对如何以及何时释放视图控制器以及它可能对响应者链或加载视图的其他行为产生的副作用(如果有)产生混淆。



<相反,请重新考虑使用NSBundle并利用所有者参数的强大功能。

  @interface ProgressViewContainer:NSObject {

}

@property(nonatomic,retain)IBOutlet ProgressView * progressView;

@end

@implementation ProgressViewContainer

@synthesize progressView = progressView;

- (void)dealloc {
[progressView release];
[super dealloc];
}

@end

@interface ProgressView:UIView {

}

+(ProgressView * )newProgressView;

@end

@implementation ProgressView

+(ProgressView *)newProgressView {
ProgressViewContainer * container = [[ProgressViewContainer alloc] init ]。
[[NSBundle mainBundle] loadNibNamed:@ProgressView所有者:容器选项:nil];

ProgressView * progressView = [container.progressView retain];
[容器发布];
返回progressView;
}

@end

创建一个名为ProgressView的笔尖包含ProgressView并将其File's Owner类设置为ProgressViewContainer。现在您可以创建从笔尖加载的ProgressView。

  ProgressView * progressView = [ProgressView newProgressView]; 
[scrollView addSubview:progressView];
[progressView release];

如果您有多个配置的进度视图,那么您可能希望实现 -initWithNibNamed: ProgressView上的方法而不是 + newProgressView ,因此您可以指定用于创建每个ProgressView实例的nib。


Ok, here's another question.

I am creating a UIView called ProgressView that is a semi-transparent view with an activity indicator and a progress bar.

I want to be able to use this view throughout different view controllers in my app, when required.

I know of 3 different ways of doing this (but I am only interested in one):

1) Create the entire view programatically, instantiate and configure as required. No worries I get that one.

2) Create the UIView in interface builder, add the required objects and load it using a method like the below. Problem with this is that we are basically guessing that the view is the objectAtIndex:0 because nowhere in the documentation I found a reference to the order of the elements returned from the [[NSBundle mainBundle] loadNibName: function.

NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"yournib" 
                                                 owner:self 
                                               options:nil];
UIView *myView = [nibContents objectAtIndex:0];
myView.frame = CGRectMake(0,0,300,400); //or whatever coordinates you need
[scrollview addSubview:myView];

3) Subclass UIViewController and let it manage the view as per normal. In this case I would never be actually pushing the view controller onto the stack, but only its main view:

ProgressViewController *vc = [[ProgressViewController alloc] initWithNibName:@"ProgressView" bundle:nil];
[vc.view setCenter:CGPointMake(self.view.center.x, self.view.center.y)];
[self.view addSubview:vc.view];
[vc release];

As far as I can tell, #3 is the the correct way of doing this (apart from programatically) but I am not entirely sure if it is safe to release the ProgressView's view controller whilst another controller's view is retaining its main view (gut feel says it is going to leak?)?

What do I do in terms of memory management in this case, where and when should I release the ProgressView's view controller?

Thanks in advance for your thoughts.

Cheers,

Rog

解决方案

I think that your solution #3 adds unnecessary complexity by introducing a UIViewController instance just as a container for your ProgressView so that you can setup nib bindings. While I do think that it is nice to be able to work with an IBOutlet bound property rather than iterating through the nib contents you can do so without introducing a UIViewController whose behavior you neither need nor want. This should avoid your confusion around how and when to release the view controller and what, if any, side effects it might have on the responder chain or other behaviors of the loaded view.

Instead please reconsider using NSBundle and taking advantage of the power of that owner argument.

@interface ProgressViewContainer : NSObject {

}

@property (nonatomic, retain) IBOutlet ProgressView *progressView;

@end

@implementation ProgressViewContainer

@synthesize progressView = progressView;

- (void) dealloc {
    [progressView release];
    [super dealloc];
}

@end

@interface ProgressView : UIView {

}

+ (ProgressView *) newProgressView;

@end

@implementation ProgressView

+ (ProgressView *) newProgressView {
    ProgressViewContainer *container = [[ProgressViewContainer alloc] init];
    [[NSBundle mainBundle] loadNibNamed:@"ProgressView" owner:container options:nil];

    ProgressView *progressView = [container.progressView retain];
    [container release];
    return progressView;
}

@end

Create a nib named "ProgressView" containing a ProgressView and set it's File's Owner class to ProgressViewContainer. Now you can create ProgressViews loaded from your nib.

ProgressView *progressView = [ProgressView newProgressView];
[scrollView addSubview:progressView];
[progressView release];

If you have multiple configurations of your progress view then maybe you'll want to implement a -initWithNibNamed: method on ProgressView instead of +newProgressView so you can specify which nib to use to create each ProgressView instance.

这篇关于从nib文件加载UIView而不需要猜测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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