我对iPhone编程很陌生,昨天正在尝试使用视图控制器和nib文件尝试不同场景的应用程序。所以,我用FirstViewController(简称FVC)和FVC.xib开始了一个新的应用程序。
我在FVC.xib中放置了一个快速视图并运行了应用程序 - 查看显示,很棒。
我现在想要在主视图上添加第二个视图。所以我继续创建了SecondViewController.xib(SVC),但没有创建.m和.h文件。我尝试从同一个视图控制器加载这两个视图,这就是我的问题所在:
我在FVC.xib中创建了一个按钮并创建了一个这样的IBAction:
- (IBAction)loadSVC {
FirstViewController *viewController = [[FirstViewController alloc] initWithNibName:@"SecondViewController" bundle:[NSBundle mainBundle]];
secondView = viewcontroller.view;
[viewController release];
[self.view addSubView:secondView];
}
所以这很好用,并添加了SVC.xib的内容,但是当我尝试从superview中删除该视图时,应用程序崩溃了:
[secondView removeFromSuperview];
如果我实际为SVC创建一个视图控制器,使用它来实例化我在FVC中的视图,并将删除代码移动到SVC:
[self.view removeFromSuperview];
一切正常。我的问题 - 我有点理解我的第一种方法崩溃的原因,但我希望有人可以解释为什么以及幕后发生的事情。我仍然是一个面向对象编程的菜鸟,所以在我的第一种情况下,我创建一个新的FirstViewController实例并将其视图添加到self.view中实际发生了什么?为什么我不能发布它(我假设因为原始视图与FirstViewController相关联,当我使用第二个xib创建一个新实例时,它会混淆一切) - 我喜欢对正在发生的事情进行更加技术性的解释。 ..
非常感谢!!
编辑以添加更多信息以回应Nick的回复
尼克 - 所以你的回答确实清楚了我对保留计数等方面的想法...我做了另一个测试应用试图让这个工作从单个视图控制器 - 例如,想想我想要向用户显示警告或欢迎消息(我知道在一个真实的应用程序中有不同的方法来实现这一点,但这更多的是学习经验) - 所以我有我的主视图@ MainViewController和布局我的警报消息xib叫做alert.xib - 所以警报消息后面没有逻辑,没有理由让它有一个我可以看到的视图控制器,我的最终目标是从主视图的视图中加载/卸载它在我的主视图之上控制器(或理解为什么不可能)
我按照你的推荐使用实例变量尝试了这个:
在MainViewController.h中:
#import <UIKit/UIKit.h>
UIViewController *secondController;
UIView *secondView;
@interface MainViewController : UIViewController {
}
@property(nonatomic, retain) UIViewController *secondController;
@property(nonatomic, retain) UIView *secondView;
- (IBAction)loadSecond;
- (IBAction)removeSecond;
@end
在MainViewController.m中:
#import "MainViewController.h"
@implementation MainViewController
@synthesize secondController, secondView;
- (IBAction)loadSecond {
secondController = [[MainViewController alloc] initWithNibName:@"alert" bundle:[NSBundle mainBundle]];
secondView = secondController.view;
[self.view addSubview:secondView];
}
- (IBAction)removeSecond {
//I've tried a number of things here, like [secondView removeFromSuperview];, [self.secondView removeFromSuperview];, [secondController.view removeFromSuperview];
}
- (void)dealloc {
[secondController release];
[secondView release];
[super dealloc];
}
所以 - 这可以加载警报视图,但是removeSecond按钮什么都不做(我确实使用NSLog来验证removeSecond方法被触发) - 为什么?
其次,最重要的是 - 这是可能的,还是可怕的做法?我操作的每个笔尖/视图都应该有自己的视图控制器吗?我错误地认为我可以创建一个MainViewController的新实例并使用它来显示和删除这个无功能,非常临时的视图? (是的,我意识到我可以轻松地以编程方式创建此视图或以更多方式完成最终目标,这将更容易,但我正在努力学习这些东西,我认为解决这个问题会有所帮助...
感谢您的帮助!
答案 0 :(得分:3)
view
,导致控制器创建视图并致电代理人(即viewDidLoad
)viewDidUnload
),但是由于创建视图的控制器被释放而且那段内存是......其他:)这就是第一种方法不起作用的原因。
第二种方法 NOT 正确,但它起作用是因为:
[self release]
或类似的东西,不是说你应该:),只是一个例子),然后视图没有' t达到0(零)保留计数并且仍然存在 - 这意味着其子视图未被删除希望这有助于理解为什么两种方法的行为都不同
答案 1 :(得分:1)
secondView
属性或iVar。同样在loadSecond
代替secontController = bla
,您需要self.secondController = bla
,否则您只需指定对iVar的引用,而不是通过设置器。这是你如何做到的(其中一种方法):
UIView *result = nil;
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:@"MyNibName" owner:owner options:nil];
for ( id o in bundle ) {
if ( [o isKindOfClass:[UIView class]] ) {
result = (UIView *)o;
break;
}
}
此处的结果将包含MyNibName
中的第一个UIView。您可以使用其他条件来确定您是否获得了所需的视图(标签,类型......)