views:

462

answers:

6

I have a text field entry in my view that I would like to block access to during a background operation. I've tried using the editable property, which successfully blocks access during the background operation, but the moment I set editable to YES, the keyboard comes up and the textfield becomes the first responder. Dismissing the keyboard just after changing editable doesn't do anything:

// Broken code
textView.editable = YES;
[textView resignFirstResponder];

I've thought about adding a clear UIView that just blocks access to the UITextView after dismissing the keyboard, but that seems like overkill. Is there a correct way to handle this?

Just so people don't have to read farther than the selected answer: It turns out that this is a "known issue" in the SDK, and you can find it listed in the release notes. Using userInteractionEnabled performs the same function, as long as you make sure to dismiss the keyboard yourself.

+5  A: 

Try textView.userInteractionEnabled = NO;

Nikolai Ruhe
A: 

Put a UIView in front of the UITextView with a dark (or white) background color and alpha set low (like 5%) sized to fully cover the textview. Default it to hidden.

When you want the textinput disabled, send it a resignFirstResponder then show the hidden layer on top. It intercepts user inputs (and ignores it). The alpha color will make it look 'dimmed.' Once your background operation is done just set the cover view to hidden and you're good to go. If you want to get fancy you can do UIView alpha fade animations.

Ramin
A: 

I'm not sure of a "correct way" but I'd probably do the transparent view solution... I agree that it seems like overkill but the simple solution is often a good answer.

Since the view gets focus upon changing the editable properties this would be easier.

the other solution that I can think of is to derive a custom UITextView and recode the editable property (or make a new method) that can accomplish what you are trying to do. This is a good object oriented solution but this could be come cumbersome.

You might also consider using a Category to add the functionality. But for either of these solutions, are still back to square one of how to accomplish what you need...

Frank V
A: 

Thank god someone came up with a better response. I originally built it with the following blocker, but the userInteractionEnabled BOOL is much easier.

It turns out that the problem is a known issue with UITextView. My workaround:

#import <UIKit/UIKit.h>

/**
 God damn SDK bug means that you can't use editable to enable/disable a 
 UITextView (It brings up the keyboard when re-enabling)
 */
@interface StupidF_ingTextViewBlocker : UIView {
}
@end


@implementation StupidF_ingTextViewBlocker

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
        self.backgroundColor = [UIColor clearColor];
        self.opaque = NO;
    }
    return self;
}

- (void)dealloc {
    [super dealloc];
}

@end

Then in place of the code I've placed above (instead of using editable). To disable (assuming I have an iVar called blocker):

// Put this in a lazy loading property or in loadView
blocker = [[StupidF_ingTextViewBlocker alloc] initWithFrame:writeView.frame];

// The blocker code  ~= textView.editable = NO
[self.view addSubview:blocker];

// Removing the blocker ~= textView.editable = YES
[blocker removeFromSuperView];
Douglas Mayle
Respectfully, please check out my solution... I really do think that is the best solution for what you are trying to accomplish.
Frank V
A: 

Subclass UITextView, and implement a single method:

- (BOOL) canBecomeFirstResponder { return NO; }
Dave DeLong
Sorry, but this doesn't work... canBecomeFirstResponder isn't called when changing the editable property
Douglas Mayle
Why downvote? I think it's a good idea.
Nikolai Ruhe
Downvote because it's not an actual working solution, to prevent people from doing the wrong thing
Douglas Mayle
A: 

Use the UITextViewDelegate. You'll need to swap out the delegate object depending on the current state.

If in the blocked state, then you'll use a delegate where textViewShouldBeginEditing returns NO.

the other delegate's textViewShouldBeginEditing would return YES.

Frank V
Sorry, this doesn't work either... The editable property doesn't call the standard set of methods. It's a bug in UITextView
Douglas Mayle
Thanks for giving it a try. I deleted "this should be the desired solution" since it doesn't work.
Frank V