开发者

Why calling [self becomeFirstResponder] caused so many problems?

For the past few extremely frustrating days of my life, I've been trying to figure out what's wrong with me code. In a certain page, if I put UITextViews or UITextFields or a MFMailComposer or a MessageComposer or anything with fields that require editing, the fields just wouldn't respond to touches. I couldn't edit anything when I ran the app. I couldn't edit text views or email fields or anything. I tried everything, but nothing worked. It turns out that on the main page (MainVC) that leads to the page where fields don't respond (GiftVC), in the viewDidAppear method (in the MainVC), I say: [self becomeFirstResponder];.

Now I'm not really sure why I put that there, but it turns out that commenting that line out fixes everything and makes all the fields and textviews and email composers and everything work just fine again.

I also have this in the MainVC page:

-(BOOL)canBecomeFirstResponder {
    return YES;
}

and commenting that out fixes the problem as well.

The weird part is that even with the [self becomeFirstResponder] line, everything worked just fine in the new iOS 5 (simulator and device), but in iOS 4 (开发者_如何学Gosimulator and device), it wouldn't work at all with that line. Now that I've removed it, it works fine in both cases.


If you have the following in your UIViewController subclass

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    if (self.view.window) {
        [self becomeFirstResponder];
    }
}

then you probably intended to allow that subclass to handle motion events (shaking) or something similar. So that's probably why it's there.

If you weren't able to edit UITextFields then this subclass was probably becoming the first responder and not forwarding the event to the actual UITextField. When a UIViewController subclass calls overrides canBecomeFirstResponder to return YES and makes them self the first responder (ie [self becomeFirstResponder], if you want don't want that custom class to handle the touch events for the UITextField, then you should override the nextResponder method.

An example from my own product -- Essentially I have a UIViewController subclass that does two things: 1) it handles shake events and 2) it displays another view modally when some button is tapped. On the modal view there are some UITextFields. To allow my UIViewController subclass to forward the touch events to my modal view, I added the following:

- (UIResponder *)nextResponder
{
    if (!self.view.window) {
        // If the modal view is being displayed, forward events to it.
        return self.modalViewController;
    } else {
        // Allow the superclass to handle event.
        return [super nextResponder];
    }
}

This will work on iOS 4 and 5, with either sdk.

Now, in your case you obviously didn't remember adding the code to become first responder in the first place, so you don't need the above hooks. However, it's good to know for the future.

Back to your actual question -- once you updated your SDK to 5, why wouldn't things work on iOS 4, but they would work on iOS 5? iOS 5 is doing some of the event forwarding for you which is why it works there. It should have never worked on iOS 4 in the beginning. Apple fixed some bugs that allowed it to work on 4, which is why it no longer works on 4.

I know the question had already accepted an accepted answer; I just wanted to clear up any confusion out there.


Check if MainVC has a method called canResignFirstResponder that returns NO (at least sometimes). If so, then once it becomes first responder, it won't let anything else become first responder, until it returns YES from that method. (All the UITextViews, etc. have to become first responder to be edited.)

Actually just look everywhere in all your code for canResignFirstResponder, in case it's in a superclass or something.

Otherwise the only thing that would stop the text fields and views from being editable would probably be if they got set userInteractionEnabled = NO, but since it hinges on the becomeFirstResponder statement, it is more likely to do with canResignFirstResponder.


In iOS 4, a subclass must override canBecomeFirstResponder in order to be able to become first responder. Maybe this is different for iOS 5 or it's a bug.


Try this, Make sure you have added the uiTextViewDelegate and

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
    NSLog(@"textViewShouldBeginEditing:");
    return YES;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜