ios - 以编程方式设置 UIViewController 的 View 和生命周期

标签 ios uiview uiviewcontroller mkmapview xib

我的应用程序中有几个针对 iOS 7+ 的 View ,它们显示 MKMapView。我希望有一个 UIViewController 来管理那些 MKMapView View ,所以我尝试创建一个 UIViewController 符合 MKMapViewDelegate< 的子类协议(protocol):

@interface MapViewController : UIViewController <MKMapViewDelegate>

MapViewController 类没有关联的 nib 文件。然后,在管理 View 的 View Controller 中,我想在其中显示一个 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: 没有被调用?

提前致谢

最佳答案

这里有两个问题:

  • 您不应该设置 UIViewControllerview 属性。事实上,您应该将 UIViewController 的 View 层次结构视为私有(private)。
  • 您应该使用 Apple 的 UIViewController 包含 API 以确保正确调用 viewWillAppear: 等。

所以这是你应该做的:

必须在 MapViewController-loadView 中创建 MKMapView:

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

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

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

当您出于任何原因从 View 层次结构中删除子 ViewController 时,您应该这样做:

[self.mapController willMoveToParentViewController:nil];
[self.mapController.view removeFromSuperview];
[self.mapController removeFromParentViewController];

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

View Controller 如何加载它的 View ?

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

- (UIView *)view
{
    [self loadViewIfNeeded];

    return _view;
}

- (void)loadViewIfNeeded
{
    if (_view == nil) {
        [self loadView];
        [self viewDidLoad];
    }
}

当您访问 View Controller 的 view 属性时,它会检查 view 是否实际上为 nil。如果为 nil,它会在返回 view 之前调用 -loadView,然后调用 -viewDidLoad

因此,当您在第一次访问之前设置 View 属性时,-loadView-viewDidLoad 将永远不会被调用。

关于ios - 以编程方式设置 UIViewController 的 View 和生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27924243/

相关文章:

ios - 为什么我的模拟器仍然显示节点数和FPS? [SpriteKit]

ios - Swift 4 + 调配 viewWillAppear()

iphone - 在 iOS 上使用动画从右到左调整 View 大小

iOS - 使用分隔 View 调整垂直 View 的大小

swift - 如何将 UIView 存储在 CoreData 或 UserDefaults 中

iPhone 5 屏幕截图未显示在 iPhone 5 App Store 上

ios - Xamarin Mac 硬件性能与较旧的翻新硬件

iPhone - 创建加载 View

swift - 自定义 UIViewControllerAnimatedTransitioning 完成后显示黑屏

ios - 向多个 subview Controller 发送消息的最佳方式