iOS中UIView的viewDidLoad方法

73

在ViewController中,使用ViewDidLoad方法可以知道VC何时已加载。

对于UIView,当视图加载时,我应该使用哪个方法?

这个方法会随着任何init调用吗?

编辑: 没有XIB,只是通过编程方式。


取决于你从哪里加载它... - borrrden
1
嗨,谢谢。我正在从一个视图控制器加载视图。 - manuelBetancurt
7个回答

59

如果从XIB文件中加载,那么当加载完成后 awakeFromNib 方法会被调用一次:

override public func awakeFromNib() {
    super.awakeFromNib();

    // ... loading logic here ...
}

更新: 如果没有XIB文件,您可能需要使用来自文档观察视图相关更改区域的方法之一进行推断(例如,didMoveToSuperview)。但更好的方式是在可能的情况下从视图控制器的viewDidLoad方法向您的视图发送消息。


1
嗨,谢谢。我会编辑我的问题,没有XIB,只是编程实现。 - manuelBetancurt
如果UIView被重新加载,它会再次触发吗? - dumbledad
@IBOutletdidMoveToSuperview() 中尚未设置。 - meaning-matters

14

您可以使用 willMove(toSuperview newSuperview: UIView?)

import UIKit

final class myView: UIView {

  override func willMove(toSuperview newSuperview: UIView?) {
     super.willMove(toSuperview: newSuperview)
     //Do stuff here
   }

} 

Apple文档


@IBOutletdidMoveToSuperview() 中还没有被设置。 - meaning-matters

8

实际上,对于视图的初始化,您无需使用视图控制器方法viewDidLoad()。您想要做的所有事情,都可以在视图的init方法中完成。 例如,在视图控制器的viewDidLoad()方法中,有一些初始化代码:

- (void)viewDidLoad{
    [super viewDidLoad];

    // init your parameters here
}

类比地说,在您的视图的 init 方法中:
- (id)initWithDelegate:(id)_delegate
{
    self = [[[[NSBundle mainBundle] loadNibNamed:@"YourView" owner:self options:nil] objectAtIndex:0] retain];
    if (self) {
        [super init];

        self.delegate = _delegate;

        // init your parameters here

        return self;

    }
    return nil;
}

然后,您可以像这样从视图控制器创建 YourView:
YourView view = [[YourView alloc] initWithDelegate:self];
[self.view addSubview:view];
[view release];

此外,当视图加载完成后您想要执行的操作,可以放在视图的layoutSubviews方法中,如下所示:

-(void)layoutSubviews{
    [super layoutSubviews];

    // init your parameters here, like set up fonts, colors, etc...
}

我认为这就是你需要的。 祝好!

6

Swift 2:

import UIKit

class myView: UIView {

  override func layoutSubviews() {
    print("run when UIView appears on screen")
    // you can update your label's text or etc.
  }
}

1
这与Swift 2无关。它是基于约束的布局的重写点。引用框架中的注释:“重写点。由layoutIfNeeded自动调用。从iOS 6.0开始,当使用基于约束的布局时,基本实现将应用基于约束的布局,否则不执行任何操作。” - Paweł Brewczynski
29
警告:layoutSubviews 方法可能会被触发多次,绝不能用于任何设置代码(如 viewDidLoad)。请注意不要改变原意并使翻译通俗易懂。 - Charlton Provatas

2

我曾经遇到过类似的问题,并找到了相对简单的解决方案。思路是在适当的时间将viewDidLoad发送给每个子视图,并在你感兴趣的类上重载该方法。

为此,在你的类中添加以下代码部分...

//  UIViewController
- (void)viewDidLoad
{

    [super viewDidLoad];

    [self.view viewDidLoad];
}


//  UIView+Loading.m
#import < UIKit/UIKit.h>

@implementation UIView (Loading)

- (void)viewDidLoad
{

    for (UIView* subview in self.subviews)

        [subview viewDidLoad];
}

@end


//  UIView+Loading.h
#import < UIKit/UIKit.h>

@interface UIView (Loading)

- (void)viewDidLoad;

@end


// UIView_CustomImplementation

- (void)viewDidLoad
{

    NSLog(@"Do whatever you want to do in custom UIView after method viewDidLoad on UIViewController was called");

}

0
据我所知,除了init方法外,我不认为有这样的方法。通常我会在init方法中进行准备工作。您可以创建自己的viewDidLoad方法并手动调用它。但是大多数情况下,UIView由其视图控制器管理,因此视图控制器应该知道何时加载视图,如果您想配置视图,则可以在视图控制器中进行。顺便说一下,viewDidLoad方法并不总是被调用。

7
我从未见过viewDidLoad不被调用。在什么情况下它才不会被调用? - devios1
@devios1,我会假设你在viewDidLoad之后以编程方式插入了子视图。 - moger777

-6

它不完全是这样工作的。

- (void)viewDidLoad在视图控制器被加载时并不会被调用;它是在视图控制器的视图被加载时才会被调用。

因此,您可以创建UIViewController,并且唯一被调用的方法是用于初始化它的init方法。视图不会被创建,-(void)viewDidLoad方法也不会被调用等。

然后,当其他东西通过以下方式请求其视图控制器的视图时:

viewController.view;

视图控制器随后调用:
- (void)loadView; // This is where you put your own loading view information, and set the viewController's self.view property here.

接下来是:

- (void)viewDidLoad;

View Did Load 是一个单独的方法,因此您不必打断实际的 loadView 方法和复杂的视图加载选项。当使用 nibs 等时,子类化和覆盖 loadView 方法可能会导致开发人员不确定 Apple 在做什么以及他们的最佳实践是什么时出现问题,因此将该方法分离出来是明智的。

然后,当内存警告出现时,视图被释放并设置为 nil:

- (void)viewWillUnload;
// view unloaded and set to nil.
- (void)viewDidUnload;

4
这个回答并不完全反映问题的要点...提问者不想要视图控制器。 - KoreanXcodeWorker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接