我们经常遇到的需求就是,当某个界面出现的时候,就刷新一下此界面的数据 保证用户的数据处于一种相对同步的情况 在 iOS 中 viewDidAppear 在界面出现的时候总是会执行一次 如此只需要在 viewDidAppear 'didBlur', payload); } ); // Remove the listener when you are done didBlurSubscription.remove(); viewDidAppear navigation.addListener didFocus 如下代码: componentDidMount() { // 添加监听 this.viewDidAppear console.log(obj) } ) } componentWillUnmount() { // 移除监听 this.viewDidAppear.remove
:) swizzledSel:@selector(wd_viewDidAppear:)]; [MKRuntime exchangeInstanceMethodImpForClass:[self class 但是我的项目中还接入了TalkingData,它在另一个地方也勾住了ViewController的 viewDidAppear 和 viewDidDisappear 这两个方法,如下: :) swizzledSel:@selector(wd_viewDidAppear:)]; [MKRuntime exchangeInstanceMethodImpForClass:[self class :(BOOL)animated { [self wd_viewDidAppear:animated]; [TalkingData trackPageBegin:[self pageName]];} - class] originalSel:@selector(viewDidAppear:) swizzledSel:@selector(mk_viewDidAppear:)];} - (void)mk_viewDidAppear
BOOL)animated{ [super viewWillDisappear:animated]; NSLog(@"viewWillDisappear_原生的"); } - (void)viewDidAppear :(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"viewWillDisappear_原生的"); } + (void) :(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"viewDidAppear_ExchangeMethod1"); } :(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"viewDidAppear_ExchangeMethod2"); } 控制台日志: RuntimeViewController2 viewDidAppear_ExchangeMethod2 此日志说明category的方法会覆盖宿主类的方法,而多个category
return YES; } 方案三(推荐) 给 UIViewController 添加类别(这里的类别不需要导入可直接使用) 然后在 load 方法里面用 Method Swzilling 方法替换交换 ViewDidAppear implementation UIViewController (HideNavBackTitle) +(void)load { swizzleMethod([self class], @selector(viewDidAppear :), @selector(ac_viewDidAppear)); } //设置导航栏返回按钮文字 - (void)ac_viewDidAppear{ self.navigationItem.backBarButtonItem target:self action:nil]; [self ac_viewDidAppear
{ super.viewWillAppear(animated) print("viewWillAppear") } override func viewDidAppear (_ animated: Bool) { super.viewDidAppear(animated) print("viewDidAppear") } loadView viewDidLoad viewWillAppear updateViewConstraints viewWillLayoutSubviews viewDidLayoutSubviews viewDidAppear 分析 ---- 直接修改Frame viewDidAppear 才能确定布局,需要在这个方法直接修改frame。
:(BOOL)animated { [super viewDidAppear:YES]; NSLog(@"FirstVC viewDidAppear"); } -(void)viewDidDisappear 28.842 SIMAlbum[33599:524075] FirstVC viewDidLoad 2016-03-24 10:31:28.897 SIMAlbum[33599:524075] FirstVC viewDidAppear [35103:546098] FirstVC viewDidLayoutSubviews 2016-03-24 10:55:17.769 SIMAlbum[35103:546098] FirstVC viewDidAppear SIMAlbum[35103:546098] FirstVC viewDidDisappear 2016-03-24 10:55:39.413 SIMAlbum[35103:546098] SecondView viewDidAppear :546098] SecondView viewDidLayoutSubviews 2016-03-24 10:56:11.055 SIMAlbum[35103:546098] SecondView viewDidAppear
2、渲染时间 在UIViewController的生命周期中,Viewdidload和Viewdidappear之间的时间可以认为是“UI渲染时间”,我们可以通过统计二者之间的时间差距来统计页面的渲染时间 :), @selector(ht_viewDidAppear:)); monitor_exchangeInstanceMethod([self class], @selector(viewWillDisappear %@毫秒",NSStringFromClass([self class]),@(pass)); self.didLoadTime = @(0); } [self ht_viewDidAppear :animated]; } 通过method swizzling方法,已经将viewdidload和viewdidappear方法替换成了自定义的ht_ViewDidLoad以及ht_viewDidAppear 注意从下一个界面返回这个界面时也会调用viewdidappear,需要避免这个统计。
增加了新的生命周期函数viewIsAppearing(),调用时机介于viewWillAppear()与viewDidAppear()之间,并且兼容到 iOS 13。 super.viewWillLayoutSubviews() print(#function) } // MARK: view完全显示 override func viewDidAppear (_ animated: Bool) { super.viewDidAppear(animated) print(#function) } // MARK ) } // MARK: view彻底消失 override func viewDidDisappear(_ animated: Bool) { super.viewDidAppear
页面生命周期 viewDidLoad: 载入完成,可以进行自定义数据以及动态创建其他控件 viewWillAppear: 视图即将出现在屏幕之前 viewDidAppear: 视图已经在屏幕上渲染完成 :(BOOL)animated{ [super viewDidAppear:animated]; //继承了UIViewController的viewDidAppear方法 所以想使用拦截viewDidLoad和viewDidAppear这两个函数,就拦截器中打印时间就可以了。 方法 */ [UIViewController aspect_hookSelector:@selector(viewDidAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo){ NSLog(@"%@ 对象的viewDidAppear调用了",aspectInfo.instance
NSLog(@"%s", __func__); self.view.backgroundColor = [UIColor redColor]; } -(void)viewDidAppear :(BOOL)animated{ NSLog(@"%s", __func__); [super viewDidAppear:animated]; YFViewController init] -[YFViewController loadView] -[YFViewController viewDidLoad] -[YFViewController viewDidAppear YFViewController init] -[YFViewController loadView] -[YFViewController viewDidLoad] -[YFViewController viewDidAppear ViewController awakeFromNib] -[ViewController loadView] -[ViewController viewDidLoad] -[ViewController viewDidAppear
Default does nothing //视图已经显示 - (void)viewDidAppear:(BOOL)animated; // Called when the view has been 2.2 viewDidAppear 这个方法表面上看上和viewDidLoad没有什么区别啊。 但是请注意一下细节。官方是这么描述viewDidLoad。 我们再来看看viewDidAppear的描述: Called when the view has been fully transitioned onto the screen 意思是视图出现在屏幕上之后才调用 w:414.000000 h:672.000000 有没有发现在viewWillAppear、viewDidAppear获取的长宽不一致?? 从上面的结果可以看到,如果需要调整空间的frame,其实是放在viewDidAppear中最靠谱的。
后来发现,在ViewDidAppear中添加自定义的tabBar就可以了。暂时仍不明所以。 添加代码: - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:YES]; // 在这里添加自定义的tabBar就可以让自定义
:), @selector(swizzled_viewDidAppear:)); } - (void)swizzled_viewDidAppear:(BOOL)animated{ // call original implementation [self swizzled_viewDidAppear:animated]; // Begin statistics Event Trace #pragma mark - 2.使用Aspects框架 + (void)load{ [UIViewController aspect_hookSelector:@selector(viewDidAppear @implementation TraceManager + (void)setUpWithConfig:(NSDictionary *)configDic{ // hook 所有页面的viewDidAppear 事件 [UIViewController aspect_hookSelector:@selector(viewDidAppear:)
class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) navigationController?. class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 放到导航条 navigationItem.rightBarButtonItem = UIBarButtonItem
2、在你需要对晃动事件进行处理的ViewController中添加如下代码: -(BOOL)canBecomeFirstResponder{ return YES; } -(void)viewDidAppear :(BOOL)animated{ [super viewDidAppear:animated]; [self becomeFirstResponder]; } (void)viewWillDisappear
究其原因是A present B,而A还没有完成显示步骤(whose view is not in the window hierarchy),正常情况下我们需要在viewDidAppear之后才能成功 通过异步串行的模式,我们可以使得弹出窗口的时间点会在viewDidAppear后被执行。
import UIKit class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool ) { super.viewDidAppear(animated) // 显示工具条 navigationController?. import UIKit class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool ) { super.viewDidAppear(animated) // 放到导航条 navigationItem.rightBarButtonItem
viewWillAppear:控制器的view将要显示 viewWillLayoutSubviews:控制器的view将要布局子控件 viewDidLayoutSubviews:控制器的view布局子控件完成 viewDidAppear viewWillLayoutSubviews:ViewController1 viewDidLayoutSubviews:ViewController1 viewDidDisappear:ViewController1 完全消失 viewDidAppear 小结: 整个控制器声明周期: viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear -> viewWillDisappear -> viewDidDisappear 说明 viewWillLayoutSubviews 在 viewWillAppear 之后 viewDidAppear
import UIKit class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool ) { super.viewDidAppear(animated) showMenuInButton() } // MARK: 给UIButton添加菜单
UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear (_ animated: Bool) { super.viewDidAppear(animated) // 存储 Task {