以编程方式设置UIViewController的视图和生命周期

时间:2015-01-13 14:20:24

标签: ios uiview uiviewcontroller mkmapview xib

我的iOS 7+应用程序中有几个显示MKMapView的视图。我希望有一个UIViewController来管理这些MKMapView次观看,因此我尝试创建符合UIViewController协议的MKMapViewDelegate子类:

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

这样,我可以看到viewWillAppear:中的MapViewController方法被调用,但viewDidLoad:方法不是。

这是做我想要的正确方法吗?为什么viewDidLoad:没有被调用?

提前致谢

1 个答案:

答案 0 :(得分:2)

这里有两个问题:

  • 您不应设置view的{​​{1}}属性。实际上,您应该将UIViewController的视图层次结构视为私有。
  • 您应该使用Apple的UIViewController包含API来确保正确调用UIViewController等。

所以这就是你应该做的:

必须在viewWillAppear:的{​​{1}}中创建MKMapView

-loadView

将子ViewController添加到视图层次结构时,您应该这样做:

MapViewController

当您从视图层次结构中删除子ViewController时,无论出于何种原因,您应该这样做:

- (void)loadView
{
    MKMapView *map = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
    map.delegate = self;
    self.view = map;
}

有关容器视图控制器的更多详细信息,请参阅 https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html

视图控制器如何加载其视图?

Apple的view属性getter实现看起来很像这样:

self.mapController = [[MapViewController alloc] init];
[self addChildViewController:self.mapController];
[self.view addSubview:self.mapController.view];
[self.mapController didMoveToParentViewController:self];

当您访问视图控制器的[self.mapController willMoveToParentViewController:nil]; [self.mapController.view removeFromSuperview]; [self.mapController removeFromParentViewController]; 属性时,它会检查- (UIView *)view { [self loadViewIfNeeded]; return _view; } - (void)loadViewIfNeeded { if (_view == nil) { [self loadView]; [self viewDidLoad]; } } 实际上是否为零。如果为零,则会在返回view之前调用view然后调用-loadView

因此,在第一次访问视图属性之前设置视图属性时,永远不会调用-viewDidLoadview