以编程方式设置 UIViewController 的视图和生命周期
Posted
技术标签:
【中文标题】以编程方式设置 UIViewController 的视图和生命周期【英文标题】:Programmatically setting an UIViewController's view and life cycle 【发布时间】:2015-01-13 14:20:24 【问题描述】:我的应用中有几个针对 ios 7+ 的视图,显示 MKMapView
。我想要一个UIViewController
来管理那些MKMapView
视图,所以我尝试创建一个符合MKMapViewDelegate
协议的UIViewController
子类:
@interface MapViewController : UIViewController <MKMapViewDelegate>
此MapViewController
类没有关联的nib
文件。然后,在管理视图的视图控制器中,我想在其中显示MKMapView
:
self.mapController = [[MapViewController alloc] init];
MKMapView *map = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
map.delegate = self.mapController;
[self.mapController setView:map];
[self.view addSubview:self.mapController.view];
这样,我可以看到MapViewController
中的viewWillAppear:
方法被调用了,但是viewDidLoad:
方法没有被调用。
这是做我想做的事情的正确方法吗?为什么不调用viewDidLoad:
?
提前致谢
【问题讨论】:
为什么不直接将MKMapView
添加到您的视图中?
【参考方案1】:
这里有两个问题:
不应设置UIViewController
的view
属性。实际上,您应该将 UIViewController
的视图层次结构视为私有的。
您应该使用 Apple 的 UIViewController
包含 API 以确保正确调用 viewWillAppear:
等。
所以你应该这样做:
MKMapView
必须在-loadView
的MapViewController
中创建:
- (void)loadView
MKMapView *map = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
map.delegate = self;
self.view = map;
当您将子 ViewController 添加到视图层次结构时,您应该这样做:
self.mapController = [[MapViewController alloc] init];
[self addChildViewController:self.mapController];
[self.view addSubview:self.mapController.view];
[self.mapController didMoveToParentViewController:self];
当您出于某种原因从视图层次结构中删除子 ViewController 时,您应该这样做:
[self.mapController willMoveToParentViewController:nil];
[self.mapController.view removeFromSuperview];
[self.mapController removeFromParentViewController];
有关容器视图控制器的更多详细信息,请参阅 https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html
视图控制器如何加载其视图?
Apple 的视图属性 getter 实现看起来很像这样:
- (UIView *)view
[self loadViewIfNeeded];
return _view;
- (void)loadViewIfNeeded
if (_view == nil)
[self loadView];
[self viewDidLoad];
当您访问视图控制器的view
属性时,它会检查view
是否实际上为nil。如果为 nil,则调用 -loadView
,然后调用 -viewDidLoad
,然后返回 view
。
因此,当您在第一次访问视图属性之前设置它,-loadView
和 -viewDidLoad
将永远不会被调用。
【讨论】:
以上是关于以编程方式设置 UIViewController 的视图和生命周期的主要内容,如果未能解决你的问题,请参考以下文章
ios UIViewController以编程方式定位按钮不起作用
无需 nib 以编程方式实例化 UIViewController
如何以编程方式从 UIViewController 转到 UITableViewController