2012-05-29 114 views
2

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

这将按预期运行,但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; 
} 
+0

我已阅读http://stackoverflow.com/questions/131062/iphone-viewwillappear-not-firing但似乎具体到导航控制器 –

+0

顺便说一句,viewWillAppear中MainVC的火灾状况良好。 –

回答

3

你的错误:你设定一个根视图控制器,然后添加其他的视图控制器视图上最重要的是。当第二个视图添加到视图层次结构中时,其视图控制器以这种方式保持“无线”状态。事实上,如果你检查你的MainViewController的parentViewController,你会注意到它是nil

为什么:的viewWillAppear中方法将只发送到根视图控制器或查看在根视图控制器的层次结构控制器(那些使用presentModalViewController:animated:presentViewController:animated:completion:已提交这一点)。

解决方案:解决这个问题,你有几个选择:

  1. 使用您的视图控制器的根视图控制器
  2. 通过上述
  3. 保持提到的方法之一出示您的视图控制器你的代码是这样的,并且手动将这些事件连接到子视图控制器(不过要小心这种方法,因为我相信你提到的事件会在iOS 5下自动转发 - 你可以很容易地检查出来)。
  4. 如果我记得正确的另一种方法,让这些事件转发到您的视图控制器是将视图控制器的视图添加到窗口,而不是父视图。
+1

谢谢 - 所以我的观点被添加了,但控制器基本上处于未连接状态?我的目标是使用MainVC加载分页滚动视图,然后添加多个MyView实例 - 基本上是相同的UI导航天气应用程序。所以这就排除了我认为的选项1和2? 3和4我需要玩一个小时。也许我正在做这个,有没有更简单的方法来设置分页滚动视图(带有可重复的内容)? –

+1

根据你的问题:是的,它可以说是断开连接。至于你能做什么:我建议你尝试拥有一个视图控制器来配置和设置几个视图,并充当滚动视图的委托。它会负责查询你的模型以了解要显示的内容,并设置不同的视图来显示正确的数据。每个需要将动作传回视图控制器的视图都可以使用块,委托或回调来实现。 – diegoreymendez

+0

为了扩展这一点,我组织iOS应用程序的首选方法是让我的自定义视图提供一个'setupWithSomeDataObject:'方法,它只接收设置其外观所需的东西。我也使用[blocks](http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html)这是(恕我直言)一个非常优雅的方式来执行行动,只要我自定义视图需要让视图控制器知道一些重要的事件被触发。 – diegoreymendez

2

有一些走错很基本的东西:

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

控制有一些更多的东西,但这些是最重要的 - 它看起来像它会为你再次阅读有关Model - View - Controller concept的整个基本概念是个好主意。接下来,您应该深入挖掘UIViewControllerUIView的课程参考资料。

即使您最终会使用您当前的方法得到您想要的结果,从长远来看它也无济于事,因为您无法正确使用所涉及的元素。

+0

我的目标是将视图逻辑从模型逻辑中分离出来。我可以很容易地使用单个视图控制器,并将所有视图设置添加到loadView,但我的感觉是,这不是很MVC - 至少不依赖于数据对象的视图设置在UIView子类中会更好?然后我只会将依赖数据对象的部分公开给控制器。也许我走了。然后对我来说第二个棘手的部分是可重用性。这就是为什么我想使用2个视图/控制器。我将重新阅读苹果MVC文档。 –

+1

模型部分通常根本不包含任何逻辑 - 大部分时间模型类或多或少地作为数据容器。然而,它仍然是一个阶级,这个事实,特别是与充斥着逻辑的视图控制器相比,可能会令人困惑。关于可重用性,作为一个经验法则:尝试封装逻辑直到这一点,在那里你可以从一个项目中获取一个UIView子类(例如),并在另一个项目中使用它,而无需进行任何更改。如果不是绝对必要的话,不要在类之间传播逻辑。最重要的是:不要担心,这可能会很棘手,但你会掌握它! – Toastor

0

在另一个视图控制器内的视图控制器上不调用方法。如果开发为iOS 5只有然后检查出UIViewController遏制可用于解决这个问题。如果您希望您的应用程序与以前的iOS版本兼容,则可以将方法调用转发给您的子视图控制器。我个人比较喜欢的子类SFContainerViewController它会自动处理:https://github.com/krzysztofzablocki/SFContainerViewController