【问题标题】:iOS: determine when all children have had layoutSubviews callediOS:确定所有孩子何时调用 layoutSubviews
【发布时间】:2013-12-24 19:10:16
【问题描述】:

似乎viewDidLayoutSubviews 在视图上调用layoutSubviews 之后立即被调用,在该视图的子视图上调用layoutSubviews 之前。有没有办法知道何时在视图上调用了 layoutSubviews 及其所有也需要更新其布局的子级?

【问题讨论】:

    标签: ios objective-c uiview uiviewcontroller layoutsubviews


    【解决方案1】:

    您不必知道子视图的子视图是否更新了它们的布局:这听起来耦合太紧了。此外,每个子视图可能会以不同的方式处理它们各自子视图的排列,并且可能根本不需要(不需要)为其子视图调用layoutSubviews。你应该只需要知道你的直接子视图。您应该或多或少地将它们视为黑匣子,而不关心它们是否有自己的子视图。

    【讨论】:

    • 我不关心视图是否有任何子视图,我只想知道视图的内容何时已完全更新,以及何时调用 viewDidLayoutSubviews 子视图中的任何内容都没有更新还没有。
    • @Thayne AFAIK,由于我上面概述的原因,普通 UIView 不会为您提供该信息:当视图的内容“新鲜”时,视图与视图不同:UIImageView 子类可能会异步获取来自网络的图像或自定义的“时钟视图”可以每毫秒刷新一次。子视图是黑盒子。超级视图可以知道它已经完成了直接子视图的布局,仅此而已。他们的 contents 是否是最新的不是 superview 关心的。我认为,您必须为此进行自定义实现。
    • 我正在使用自定义实现。我的具体问题是某些子视图正在执行异步操作,我需要等待这些操作完成,然后再执行其他操作。但是,在 didLayoutSubviews 中,还没有任何子视图操作被排队(在调度组或其他东西中)。我需要以某种方式确保在我什至不知道的操作完成之前不会运行完成操作。或者等到我知道他们。
    • @Thayne 我认为要解决您的问题,您可能需要重新考虑您的架构。听起来好像您的视图正在做很多控制器应该做的事情。让控制器完成异步操作的工作,然后让它们告诉您的视图刷新。此外,如果您需要按特定顺序运行一些异步操作(或仅在完成另一个操作时),您可能需要查看 NSOperation(Queue)。
    • 谢谢,我怀疑我们需要重新考虑架构。我没有为视图编写代码,但我知道按照我们的方式编写代码是有具体原因的。不过,解决这些问题可能比这个更容易。
    【解决方案2】:

    正如@Johannes Fahrenkrug 所说,您应该“将它们视为黑匣子”。但按照我的理解,那是因为Cocoa不能承诺。

    如果您确实需要在所有子视图完成布局工作时收到通知,这里有一个核心示例可能会解决您的问题。我也不保证它会在任何情况下都有效。

    - (void) layoutSubviewsIsDone{
        // Your code here for layoutSubviews is done
    }
    
    // Prepare two parameters ahead
    int timesOfLayoutSubviews = 0;
    BOOL isLayingOutSubviews = NO;
    
    // Override the layoutSubviews function
    - (void) layoutSubviews{
         isLayingOutSubviews = YES;  // It's unsafe here!
         // you may move it to appropriate place according to your real scenario
    
         // Don't forget to inform super
         [super layoutSubviews];
    }
    
    // Override the setFrame function to monitor actions of layoutSubviews
    - (void) setFrame:(CGRect)frame{
         if(isLayingOutSubviews){
            if(frame.size.width == self.frame.size.width
            && frame.size.height == self.frame.size.height
            && frame.origin.x == self.frame.origin.x
            && frame.origin.y == self.frame.origin.y
            && timesOfLayoutSubviews ==self.subviews.count){
                isLayingOutSubviews = NO;
                timesOfLayoutSubviews = 0;
                [self layoutSubviewsIsDone];  // Detected job done, call your function
        }else{
            timesOfLayoutSubviews++;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 2014-03-27
      • 2016-08-20
      • 1970-01-01
      相关资源
      最近更新 更多