viewWillAppear未被触发

时间:2012-05-29 15:08:57

标签: ios cocoa-touch ios5 uiview uiviewcontroller

我已经设置了一个基本的测试应用程序,它显示包含标签的视图,而不使用IB。我想使用自定义UIView子类和自定义UIViewController子类。

这将按预期运行,但MyViewController的viewWillAppear和其他类似的委托不会触发。

我发现这些火灾是什么?在以前的项目中(使用IB),这些都可以解决。

以下是完整的代码:

AppDelegate - 加载'MainVC'视图控制器并将其设置为根控制器

#import "AppDelegate.h"
#import "MainVC.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize mainVC = _mainVC;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.mainVC = [[MainVC alloc] init];
    self.window.rootViewController = self.mainVC;
    [self.window makeKeyAndVisible];
    return YES;
}

MainVC - 创建一个“MyViewController”,用于分配“MyView”(它还会传递应该用于视图的帧大小)

#import "MainVC.h"
#import "MyViewController.h"

@implementation MainVC

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        MyViewController *controller = [[MyViewController alloc] init];
        CGRect frame;
        frame.origin.x = 5;
        frame.origin.y = 5;
        frame.size.width = self.view.frame.size.width - (2 * 5);
        frame.size.height = self.view.frame.size.height - (2 * 5);
        controller.startingFrame = frame;
        [self.view addSubview:controller.view];
    }
    return self;
}

MyViewController - 创建MyView

#import "MyViewController.h"
#import "MyView.h"

@implementation MyViewController

@synthesize startingFrame;

- (void)loadView{
    self.view = [[MyView alloc] initWithFrame:startingFrame];
}

- (void)viewWillAppear:(BOOL)animated{
    NSLog(@"appearing"); //doesn't do anything
}

- (void)viewDidAppear:(BOOL)animated{
    NSLog(@"appeared"); //doesn't do anything
}

MyView的

#import "MyView.h"

@implementation MyView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 150, 40)];
        [label setText:@"Label"];
        [self addSubview:label];
    }
    return self;
}

3 个答案:

答案 0 :(得分:3)

您的错误:您正在设置根视图控制器,然后在其上添加另一个视图控制器视图。当第二个视图添加到视图层次结构中时,其视图控制器仍以这种方式保持“无线连接”。事实上,如果你检查你的MainViewController的parentViewController,你会发现它是nil

原因: viewWillAppear方法将仅发送到根视图控制器或查看根视图控制器层次结构中的控制器(使用presentModalViewController:animated:或{{ 1}})。

解决方案:要解决它,您有几个选择:

  1. 将视图控制器用作根视图控制器
  2. 通过上述方法之一呈现视图控制器
  3. 保持您的代码不变,并手动将这些事件连接到子视图控制器(但请注意这种方法,因为我相信您提到的事件会在iOS 5下自动转发 - 您可以轻松地将其检查出来。)
  4. 如果我回想一下,让这些事件转发到视图控制器的另一种方法是将视图控制器的视图添加到窗口,而不是父视图。

答案 1 :(得分:2)

有一些非常基本的问题出了问题:

  • 您正在使用initWithNibNamed:为您的MainViewController进行整个设置,但是您只需调用init即可创建它。所以你的设置永远不会发生
  • 您正在实现第二个VC(MyViewController),显然只是为了创建myView,然后将其添加到rootVC层次结构中。不好!只有一个VC(在您的情况下为MainViewController)应负责创建和管理其层次结构中的视图
  • 不要在loadView中进行VC控制器设置,就像在MyViewController中一样。在你的情况下,它是使事情工作的唯一方法,因为MyVC实际上从未完全启动并运行,但方法是错误的 - 你基本上强迫View Controller设置视图,尽管控制器本身从不在控制任何事情

还有一些东西,但那些是最重要的东西 - 看起来你再次阅读Model - View - Controller concept的整个基本概念似乎是一个好主意。接下来,您应该深入研究UIViewControllerUIView的类引用。

即使你最终会使用当前的方法得到你想要的结果,但从长远来看,这对你没有帮助,因为你不会学会正确使用所涉及的元素。

答案 2 :(得分:0)

不在另一个视图控制器内的视图控制器上调用方法。如果仅针对 iOS 5 进行开发,请查看可用于解决此问题的 UIViewController Containment 。如果您希望应用程序与以前的iOS版本兼容,则可以将方法调用转发到子视图控制器。我个人更喜欢子类化 SFContainerViewController 自动处理这个:https://github.com/krzysztofzablocki/SFContainerViewController