从一个nib文件加载UIView没有猜测

好的,还有一个问题。

我正在创build一个名为ProgressView的UIView,它是一个具有活动指示器和进度条的半透明视图。

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

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

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

2)在界面生成器中创buildUIView,添加所需的对象,并使用下面的方法加载它。 与此问题是,我们基本上猜测该视图是objectAtIndex:0,因为在文档中找不到从[[NSBundle mainBundle] loadNibName:函数返回的元素的顺序的引用。

 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)子类UIViewController,让它按照正常的方式pipe理视图。 在这种情况下,我绝对不会将视图控制器推到堆栈上,而只能看到其主视图:

 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]; 

据我所知,#3是这样做的正确方式(除编程),但我不完全确定是否可以安全地释放ProgressView的视图控制器,而另一个控制器的视图保留其主视图(直觉说它会泄漏?)?

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

预先感谢您的想法。

干杯,

ROG

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

相反,请重新考虑使用NSBundle并利用这个owner论据的力量。

 @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 

创build一个名为“ProgressView”的包含ProgressView的nib,并将它的File的Owner类设置为ProgressViewContainer。 现在你可以创build从你的笔尖加载的ProgressViews。

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

如果您有多个进度视图configuration,那么您可能需要在ProgressView上实现-initWithNibNamed:方法,而不是+newProgressView以便您可以指定使用哪个nib来创build每个ProgressView实例。

我投票select#2。 – [NSBundle loadNibNamed]的返回值是顶层对象的数组。 所以只要你的笔尖只有一个顶级对象,那么索引0就是正确的。 其他视图是子视图而不是顶级对象。

另一个select当然是为所有视图控制器创build一个超类,其中包括一个名为“progressView”的出口,然后将视图连接到笔尖的文件所有者的出口。 似乎像这样的矫枉过正,但。

我也更喜欢替代#2。 如果“0”困扰你,你可以:

  • 创build一个名为ProgressView的UIView的子类
  • 创build一个名为ProgressView.xib的nib文件来描述您的进度视图。
  • select笔尖中最顶层的视图,并在界面构build器中将其类设置为ProgressView

然后做

 NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"ProgressView" owner:self options:nil]; ProgressView *progressView = nil; for (UIView *view in nibContents) { if ([view isKindOfClass:[ProgressView class]]) { progressView = (ProgressView *) view; break; } } if (progressView != nil) { //Use progressView here } 

我结束了为这个UIView添加一个类别:

  #import "UIViewNibLoading.h" @implementation UIView (UIViewNibLoading) + (id) loadNibNamed:(NSString *) nibName { return [UIView loadNibNamed:nibName fromBundle:[NSBundle mainBundle] retainingObjectWithTag:1]; } + (id) loadNibNamed:(NSString *) nibName fromBundle:(NSBundle *) bundle retainingObjectWithTag:(NSUInteger) tag { NSArray * nib = [bundle loadNibNamed:nibName owner:nil options:nil]; if(!nib) return nil; UIView * target = nil; for(UIView * view in nib) { if(view.tag == tag) { target = [view retain]; break; } } if(target && [target respondsToSelector:@selector(viewDidLoad)]) { [target performSelector:@selector(viewDidLoad)]; } return [target autorelease]; } @end 

这里解释: http : //gngrwzrd.com/blog-view-controller-less-view-loading-ios-mac.html