2

Another cry for help about this warning.

First of all I have looked at every and all questions on here elsewhere and none seem to fit my situation. It has nothing to do with Alert boxes and resigning as first responder, nor performing any animation before views get displayed. My problem occurs when instantiating a UIView based custom keyboard.

Secondly, I believe that I can make the warning appear/disappear at will. I am just very confused as to why, so I am looking more for an explanation than a solution.

There is too much code to post here, so I'll just give an outline of what is going on:

The ViewController "Calc" instantiates a custom UIView based "DataView" in the VC's loadView method, and then adds it as a sub view of the VC.

The "DataView" instantiates a custom UITextField based "TextFieldKPD" in the DataView's init method

The "TextField" instantiates a custom UIView based "KeyPad" in the TextField's init method, and assigns that KeyPad to the TextField's inputView.

The "KeyPad" creates 13 UIButtons of type UIButtonTypeCustom, reads in and assigns a "pressed" and "not pressed" image for each button, as well as setting actions for the buttons. It then adds each button as a subview of itself. (By controlling when in the UIView lifecycle of the KeyPad that this construction occurs, is how I can effect the wait_fences warning: see below.)

The "Calc" ViewController is the one that is initially presented to the user. I have tracked down the wait_fences warning as occurring after the end of the Calc's viewDidLayoutSubViews method and before its viewDidAppear method is called. Note that the KeyPad is not visible when the Calc is displayed.

I appear to be able to control the action of the wait_fences warning by changing how the Keypad is constructed:

  • If the UIButtons are instantiated and added as subviews in the init method of the KeyPad, then I will get the warning, once and once only.

  • If, instead, the buttons are instantiated and added in the KeyPad's layoutSubViews method, then the warning does not appear. (But the KeyPad doesn't effectively get constructed until I tap on the TextField - still, no wait_fences warning then either)

There is no animation or anything in Calc's loadView. It is instantiate and assign all the way down.

So any comments on this version of wait_fences?

EDIT 1, Jan 30th - Now With Even More Confusion!

I was bored this morning so I decided to play with my code to see if I could better isolate the generation of the warning. I narrowed it down to the following, totally useless code that with which I can now trigger the warning:

-(void)loadImages
{
    UIImage* image;

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

If I perform [self loadImages] in the init method of KeyPad then the warning appears. But this code does nothing as the file does not exist. I believe that if the loop counter is small enough that the warning does go away, but I haven't qualified a lower limit.

If I replace the actual loading of the image with

[UIImage imageWithContentsOfFile:@"StupidFileNameThatDoesNotExist"]

and still call the method during the KeyPad init, then I do not seem to get the warning. One obvious difference between these two ways of loading the image is that imageNamed caches the image internally.

So I am leaning towards George's answer that it is an internal Apple screw up.

Edit 2, Feb 1 - Its a warning Jim, but not as we know it

So I convinced myself that it was the caching in the UIImage class that was obviously causing the issue. What to do about it? Well write my own image cache of course!!

So I started plugging away, rip out that code that attempted to load invalid images and got the point where I generated the file names I needed and passed them to my cache controller. So to verify that things were starting to come together, within the cache controller, I generated a NSLog message for each attempt to cache an image - nothing more - just log the file name.

And guess what - I get the stupid warning again. For doing no actual work at all.

I can only conclude that there is some sort of internal iOS race condition that I am triggering when I cram extra code into the init method of KeyPad. And that there is nothing I can do to mitigate it. All I can do is hope that this warning is benign.

Edit 3, Hamlet Act 1 scene 4: Something is rotten in the state of Denmark

Keeping the same code as in Edit 2, I commented out the NSLog statement. And the warning went away. I put it back, and the warning appears.

So the code I have is:

-(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];
        }

    }

}

And:

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

With that NSLog statement controlling the appearance of the warning.

Edit 4, Feb 2 - Welcome to the Temple of Doom

Taking Allen's comments to heart I rebuilt my keyboard as a XIB and loaded that instead of manually trying to build the view. Of course that didn't fix anything. I had hoped that the Nib loading would happen outside of what ever it is that is causing the problem.

My gut feeling is that I am butting up against a race condition within the loadView of Calc and some internal iOS activity. If I do too much work inside loadView then I cross the line and trip a wait_fences warning. And that the keyboard is a symptom and not the underlying cause. IE it could have been any activity, it was just that the keyboard work was the last thing I did before the warning started appearing. I just wish that I actually knew what the constraints were that I was actually crossing and not stumbling around in the dark.

Peter M
  • 7,309
  • 3
  • 50
  • 91
  • Peter, How big is your 26 button images? it seems the loading of these images is beyond the 10s limit as apple requires it, have you even consider to put all the UI in a nib? – Allen Feb 02 '12 at 14:27
  • @Allen .. at the moment I am not even loading the images. All I am doing is creating the names of the images and sending that information to NSLog. And I just ran a test .. from the time I hit the Run button in XCode until the warning shows up is 5 seconds. When running from my 4th gen iPod touch the App starts in less than 2 seconds. – Peter M Feb 02 '12 at 14:40
  • time your whole load time with these images, and reconsider put all these fixed UI into a nib. – Allen Feb 02 '12 at 14:47
  • @Allen .. this issue is independent of the actual images themselves (which btw are all in the 10kB size range). I will revisit the timing with the images later today. But my recollection is that the App started with similar times. As for the nib, right now I am unsure if a custom button in a nib provides the same multi-resolution image loading that comes with the "@2x" etc as provided by UIImage. And my buttons aren't stretchable. – Peter M Feb 02 '12 at 15:07
  • @Allen - Just timed it. Roughly 6 seconds from XCode->Run to warning display when actually loading the images. – Peter M Feb 02 '12 at 15:15
  • don't worry about the resolution thing, the nib loading will automatically load the @2x image in capable device. – Allen Feb 02 '12 at 15:48
  • @Allen - of course my hand crafted custom keyboard accommodates multiple layouts and physical key locations depending on what options are passed into the init. But yeah I'll be able to cope with that. So I'll look at it. – Peter M Feb 02 '12 at 15:57

5 Answers5

2

I've had this issues a few times before and attempted to find a solution. The closest that I got was that according to an apple engineer it is an issue caused internally and 3rd party developers should not worry about it. As far as I am aware it shouldn't cause your app to crash or cause any problems, other than a really annoying error in the debugger that seems to drive all developers mad!

Sorry that I couldn't be of more help.

George Green
  • 4,807
  • 5
  • 31
  • 45
  • I'm going with this answer based on my complete inability to rationally characterise the problem. even though technically this is a non-answer, my experience is showing that this issue can't be answered by mere mortals. Now who is Jon Skeet of iOS?? – Peter M Feb 03 '12 at 22:11
2

As far as i can tell about your code description, the problem seems to occur when a subview (eg. UIAlertView) is created prior to its parent/super view. Something to do with the responder chain.

Try moving the view codes around to fix the problem or paste the relevant parts.

valvoline
  • 7,737
  • 3
  • 47
  • 52
  • I moved things all over the place in order to ensure that child views were created after their parents and still had the same issue. I'm thinking that a lot of solving this issue is based on peoples superstition of what fixes caused it to disappear for their case, but not actually solving the underlying problem. – Peter M Feb 01 '12 at 22:52
0

I've ran into the wait_fences error when mistakenly running UIKit code from a background thread. It doesn't sound like that's your problem, but if you haven't yet that's another thing to look into.

Marc Charbonneau
  • 40,399
  • 3
  • 75
  • 82
  • I only have the single explicit thread that I am using. No idea what iOS is doing in the background. – Peter M Feb 01 '12 at 22:30
0

According to my knowledge. This warning appears when we are calling a UIAlertView and at the same time we are performing some operation on the UIView. To solve this problem we need not to perform operation on UIView at that time. For this we can do either of the two things : 1. We can call UIAlertView with some delay so that the operation on the UIView gets completed. 2. Or we can perform the operations on the UIView in method - (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex; So that the UIAlertView is not on our UIView at that time when some operations are performing on the UIVIew.

Hope it will help you.

kumar123
  • 791
  • 7
  • 21
  • As per my question I am not using an Alert or performing any animation. This is solely about assembling a fixed view hierarchy prior to display. – Peter M Feb 02 '12 at 13:15
0

? I'm a little unclear of your view/viewcontroller hierarchy...

You've got a ViewController "Calc" which creates a "DataView" for it's "master" view. "DataView" creates a textField "TextFieldKPD" as a subview of itself. "TextFieldKPD" then creates a UIView "KeyPad" subview which itself creates 13 UIButton subviews for itself.

So your views are 4 levels deep?

Apple state that a ViewController should handle a whole screenful of views (I guess this changed slightly now that we can create containerViews but the intent behind their assertion remains). Make sure your keypad button events and textfield events are handled by your viewController.

Surely you would be better creating all of these views in the viewController or the master view so your hierarchy is flatter?

Apologies if I've misunderstood your hierarchy.

Btw, one thing to try is removing the textfield entirely and seeing if you can still get the error.

ader
  • 5,403
  • 1
  • 21
  • 26
  • the Calc has a single view and the DataView is a subview within Calc. The rest of the hierarchy is correct. The reason I have a deep hierarchy is that the DataView (and everything in it - it does not just only include the textfield) is instantiated multiple times. In some ways it is analogous to a custom cell in a table view (but no a table view is not appropriate here) – Peter M Feb 02 '12 at 14:48
  • It sounds like a timing issue. Try using NSTimer to schedule creation of the buttons half a second later. – ader Feb 02 '12 at 15:28
  • I am already pretty certain it is a timing issue. What I want to know is why is it a timing issue. – Peter M Feb 02 '12 at 15:32
  • It might be a crazy thought but what happens if you don't use for loops to create the buttons, but create them all individually/manually? – ader Feb 02 '12 at 16:06