2

关于这个警告的另一个呼救声。

首先,我已经查看了其他地方的所有问题,但似乎没有一个适合我的情况。它与警报框和辞去第一响应者无关,也与在显示视图之前执行任何动画无关。实例化基于 UIView 的自定义键盘时会出现我的问题。

其次,我相信我可以让警告随意出现/消失。我只是很困惑为什么,所以我更多的是寻找解释而不是解决方案。

这里要发布的代码太多了,所以我将简要介绍一下正在发生的事情:

ViewController "Calc" 在 VC 的 loadView 方法中实例化一个基于 UIView 的自定义 "DataView",然后将其添加为 VC 的子视图。

“DataView”在 DataView 的 init 方法中实例化一个基于自定义 UITextField 的“TextFieldKPD”

“TextField”在 TextField 的 init 方法中实例化了一个基于 UIView 的自定义“KeyPad”,并将该 KeyPad 分配给 TextField 的 inputView。

“KeyPad”创建了 13 个 UIButtonTypeCustom 类型的 UIButton,读取并为每个按钮分配“按下”和“未按下”图像,以及设置按钮的操作。然后它将每个按钮添加为其自身的子视图。(通过控制在 KeyPad 的 UIView 生命周期中何时发生这种构造,我可以影响 wait_fences 警告:见下文。)

“Calc”视图控制器是最初呈现给用户的视图控制器。我已经追踪到在 Calc 的 viewDidLayoutSubViews 方法结束之后和调用其 viewDidAppear 方法之前发生的 wait_fences 警告。请注意,显示 Calc 时,KeyPad 不可见。

我似乎能够通过更改键盘的构造方式来控制 wait_fences 警告的操作:

  • 如果 UIButtons 被实例化并作为子视图添加到 KeyPad 的 init 方法中,那么我将收到警告,只有一次。

  • 相反,如果按钮被实例化并添加到 KeyPad 的 layoutSubViews 方法中,则不会出现警告。(但在我点击 TextField 之前,KeyPad 并没有有效地构建 - 仍然没有 wait_fences 警告)

Calc 的 loadView 中没有动画或任何内容。它一直实例化并分配。

那么对这个版本的wait_fences有什么意见吗?

编辑 1,1 月 30 日 - 现在更加混乱!

今天早上我很无聊,所以我决定玩一下我的代码,看看我是否可以更好地隔离警告的生成。我将其范围缩小到以下完全无用的代码,现在我可以使用这些代码触发警告:

-(void)loadImages
{
    UIImage* image;

    for(int i=0; i<16; i++) {
        image = [UIImage imageNamed:@"StupidFileNameThatDoesNotExist"];
    }
}

如果我[self loadImages]在 init 方法中执行,KeyPad则会出现警告。但是这个代码什么都不做,因为文件不存在。我相信如果循环计数器足够小以至于警告确实消失了,但我没有限定下限。

如果我将图像的实际加载替换为

[UIImage imageWithContentsOfFile:@"StupidFileNameThatDoesNotExist"]

并且在初始化期间仍然调用该方法KeyPad,那么我似乎没有收到警告。这两种加载图像的方式之间的一个明显区别是imageNamed在内部缓存图像。

所以我倾向于乔治的回答,这是一个内部的苹果搞砸了。

编辑 2,2 月 1 日 - 这是吉姆的警告,但不是我们所知道的

所以我说服自己,显然是 UIImage 类中的缓存导致了这个问题。该怎么办?好吧,当然是写我自己的图像缓存!!

所以我开始停止工作,撕掉那些试图加载无效图像的代码,并得到我生成所需文件名并将它们传递给我的缓存控制器的点。因此,为了验证事情是否开始融合在一起,在缓存控制器中,我为每次缓存图像的尝试生成了一条 NSLog 消息 - 仅此而已 - 只需记录文件名。

你猜怎么着——我又收到了愚蠢的警告。因为根本没有做任何实际工作。

我只能得出结论,当我将额外的代码塞进KeyPad. 而且我无能为力来减轻它。我所能做的就是希望这个警告是良性的。

编辑 3,《哈姆雷特》第 1 场第 4 场:丹麦的某些东西很烂

保持与编辑 2 中相同的代码,我注释掉了 NSLog 语句。警告消失了。我把它放回去,警告出现了。

所以我的代码是:

-(void)loadImages
{
    // Iterate over button definitions and cache the required images
    for(int i=0; i<numKeys; i++) {

        if (![imageCache imageExistsForTag:keyTags[i]]) {
            [imageCache addImageFile:[NSString stringWithFormat:@"%s_NP.png",keyNames[i]] forTag:keyTags[i]];
        }

        if (![imageCache imageExistsForTag:keyTags[i]+pressedOffset]) {
            [imageCache addImageFile:[NSString stringWithFormat:@"%s_P.png",keyNames[i]] forTag:keyTags[i]+pressedOffset];
        }

    }

}

和:

-(void)addImageFile:(NSString*)imageFile forTag:(int)tag
{
    NSLog(@"Adding tag:%d for file %@", tag, imageFile);
}

使用该 NSLog 语句控制警告的出现。

编辑 4,2 月 2 日 - 欢迎来到末日神殿

考虑到艾伦的评论,我将我的键盘重新构建为 XIB 并加载它,而不是手动尝试构建视图。当然,这并没有解决任何问题。我曾希望笔尖加载会发生在导致问题的原因之外。

我的直觉是,我正在与 Calc 的 loadView 和一些内部 iOS 活动中的竞争条件发生冲突。如果我在 loadView 中做太多工作,那么我会越界并触发 wait_fences 警告。而且键盘是一种症状,而不是根本原因。IE 它可能是任何活动,只是键盘工作是我在警告开始出现之前所做的最后一件事。我只是希望我真的知道我实际上正在穿越的限制是什么,而不是在黑暗中跌跌撞撞。

4

5 回答 5

2

我之前遇到过几次这个问题,并试图找到解决方案。我得到的最接近的是,根据苹果工程师的说法,这是内部引起的问题,第三方开发人员不应该担心。据我所知,它不应该导致您的应用程序崩溃或导致任何问题,除了调试器中似乎让所有开发人员发疯的真正烦人的错误!

抱歉,我无法提供更多帮助。

于 2012-01-28T16:28:47.490 回答
2

据我所知,您的代码描述似乎是在子视图(例如 UIAlertView)在其父/超级视图之前创建时出现的。与响应者链有关。

尝试移动视图代码以解决问题或粘贴相关部分。

于 2012-01-28T16:43:57.133 回答
0

从后台线程错误地运行 UIKit 代码时,我遇到了 wait_fences 错误。听起来这不是你的问题,但如果你还没有,那是另一回事。

于 2012-02-01T19:48:51.583 回答
0

据我所知。当我们调用 UIAlertView 并同时对 UIView 执行一些操作时会出现此警告。为了解决这个问题,我们当时不需要对 UIView 进行操作。为此,我们可以做以下两件事之一: 1. 我们可以延迟调用 UIAlertView 以便完成对 UIView 的操作。2. 或者我们可以在方法中对UIView进行操作 - (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex; 这样在UIVIew上进行一些操作的时候,UIAlertView不在我们的UIView上。

希望它会帮助你。

于 2012-02-02T11:37:07.370 回答
0

? 我有点不清楚您的视图/视图控制器层次结构......

你有一个 ViewController“Calc”,它为它的“主”视图创建一个“DataView”。“DataView”创建一个文本字段“TextFieldKPD”作为其自身的子视图。“TextFieldKPD”然后创建一个 UIView “KeyPad”子视图,它自己为自己创建 13 个 UIButton 子视图。

所以你的观点有 4 个层次?

Apple 声明 ViewController 应该处理整个屏幕的视图(我猜现在我们可以创建容器视图,但它们断言背后的意图仍然存在)。确保您的键盘按钮事件和文本字段事件由您的 viewController 处理。

当然,您最好在 viewController 或主视图中创建所有这些视图,以便您的层次结构更扁平?

如果我误解了你的层次结构,我深表歉意。

顺便说一句,要尝试的一件事是完全删除文本字段并查看是否仍然可以收到错误。

于 2012-02-02T14:40:41.127 回答