UITextField won't becomeFirstResponder - ios

I'm having a problem getting a textfield to accept the becomeFirstResponder directive.
I'm providing a custom mechanism to create a title in the navigation bar. I have another viewcontroller that is successfully using this same technique. On viewDidAppear I fire off:
- (void)addTitleTextField
{
CGRect textFrame = self.parentViewController.navigationController.navigationBar.frame;
textFrame.size.width = 300.0;
textFrame.origin.y = (768.0 - 300.0)/2;
textFrame.size.height = 30.0;
textFrame.origin.x = 7.0;
self.titleTextField = [[UITextField alloc] initWithFrame:textFrame];
self.titleTextField.placeholder = NSLocalizedString(#"New Multiple Choice Quiz", #"New Multiple Choice Quiz");
self.titleTextField.borderStyle = UITextBorderStyleRoundedRect;
self.titleTextField.font = [UIFont boldSystemFontOfSize:20.0];
self.titleTextField.textAlignment = NSTextAlignmentCenter;
self.titleTextField.backgroundColor = [UIColor whiteColor];
self.titleTextField.textColor = [UIColor blackColor];
self.titleTextField.delegate = self;
[self.titleTextField setAutocorrectionType:UITextAutocorrectionTypeNo];
self.titleTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
[self.titleTextField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
self.activeTextField = self.titleTextField;
self.parentViewController.navigationItem.titleView = self.titleTextField;
[self.titleTextField becomeFirstResponder];
}
self.titleTextField will allow me to set the text value, but if you check using canBecomeFirstResponder it returns NO. As you can see I am setting this on the parentViewController. I've tried using a delegate to attempt to get the parentViewController to set it. When I do the delegate and check whether the textField canBecomeFirstResponder it returns YES, but I'm still unable to make it accept the firstResponder order. Any ideas? The Docs say "A responder object only becomes the first responder if the current responder can resign first-responder status (canResignFirstResponder) and the new responder can become first responder".

Are you telling the UITextField to become selector on a background thread?
[textField performSelectorOnMainThread:#selector(becomeFirstResponder) withObject:nil
waitUntilDone:YES];
Rationale: Calling UIKit methods (ie updating the view) on a method other than the main thread won't work. . this could be happening. (It is not clear where the addTitleTextField method is being called from).
Is there another first responder that needs some time to resign?
[textField performSelectorOnMainThread:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
Rationale: If another field is hanging onto first responder (or in the process of resigning it), it will give it time to clean up an resign, by waiting until the next run-loop. . . . . usually the next run-loop will be enough time for the previous responder to clean up, or you could try a short delay like 0.05.

You might need to add textField to view hierarchy:
v.addSubview(textField)

Another thing to do is to make sure the textField is enabled (check Interface Builder, then any disabling you might do through code).
I spent almost an hour trying to figure out what the problem was: I got a workaround by subclassing UITextField and overriding canBecomeFirstResponder to always return true. This forced it to finally show keyboard and edit the textField, but I noticed I couldn't tap/select/copy/paste the textField. User Interaction was enabled, and then I finally saw the Enabled not being checked...I blame Apple for not displaying any visual cue when a piece of UI is disabled (like the do with Hidden) lol

Related

Configuring keyboard settings within PDFView form fields

I'm working on an app which loads PDF files from a server and displays those PDF files within a PDFView. The files contain form fields in which the user is to type. That's works fine. The PDF files are to be used in an education setting, where the spelling should not be autocorrected and predictive text should not be available.
I have not found the means to disable autocorrect in a PDFView, along the lines of autocorrectionType = false in a UITextField.
I'm aware the user can manually disable autocorrection and predictive text in device settings. That's not a viable option in this case (likely user confusion and no means to verify). I'm ok if there's a way to disable autocorrect app-wide.
We're creating the PDF files in-house, so we're ok if there's something we can do while generating the files. Adobe Acrobat is a "check spelling" option on form fields, but the setting has no effect, at least within PDFView.
Thanks.
I found a solution. It's a hack, but I'll take what I can get.
I found that when a user taps a PDF text field, PDFKit hides the PDF text field and overlays a UITextView at the same location. It makes that UITextView the first responder and brings up the keyboard. That UITextView remains until the user taps elsewhere, when it is removed and replaced with a PDF text field containing the contents of the (now dead) UITextView.
The UITextView in question is buried deep inside PDFView, within private UIView subclasses.
Below is the code I'm using. It starts with a view (the PDFView) and deep-dives looking for any UITextView it can find. When found, it resigns as first responder, changes parameters, and becomes the first responder again. The user will see the typeahead buttons appear briefly then disappear. I haven't found a way around this, as we don't gain access to the UITextView until it is already the first responder.
The code here is called via a timer executing every 0.1 seconds. I'm sure there are more efficient ways to do this but this works, and barely registers on the CPU meter.
This code also sets the pasteDelegate of the UITextView because in my case I want to override and prevent pasting of text into the UITextView. The code to do that is simple; in textPasteConfigurationSupporting just return [item setNoResult].
As with all hacks like this, be sure to test with all versions of iOS your app supports - including future versions. Apple could easily change their PDFKit implementation causing this to break or misbehave. Or better, they could add a supported means to do this.
-(void)lookForTextViewsInView:(UIView *)view
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UITextView class]]) {
UITextView *textView = (UITextView *)subview;
//NSLog(#"Found text field with contents: %#",textView.text);
if (textView.autocapitalizationType == UITextAutocapitalizationTypeNone &&
textView.autocorrectionType == UITextAutocorrectionTypeNo &&
textView.spellCheckingType == UITextSpellCheckingTypeNo &&
textView.pasteDelegate == self) {
//NSLog(#"textView %# is already adjusted", textView.text);
return;
}
if (textView.isFirstResponder) {
//NSLog(#"Adjusting and resetting first responder of %#",textView.text);
[textView resignFirstResponder];
textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
textView.autocorrectionType = UITextAutocorrectionTypeNo;
textView.spellCheckingType = UITextSpellCheckingTypeNo;
textView.pasteDelegate = self;
[textView becomeFirstResponder];
} else {
//I don't think this ever fires, but here for completion's sake
//NSLog(#"Adjusting without resetting first responder of %#",textView.text);
textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
textView.autocorrectionType = UITextAutocorrectionTypeNo;
textView.spellCheckingType = UITextSpellCheckingTypeNo;
textView.pasteDelegate = self;
}
} else {
//NSLog(#"%# is not a UITextView", [subview class]);
[self lookForTextViewsInView:subview];
}
}
}

UIButton subclass highlighting error (highlight remains or persists even after tap or touch down)

I subclassed UIButton in my app and there are many times when the highlight color stays even when I'm done pressing down the button. I can't figure out exactly what causes this since it only seems to happen by chance, but it seems to happen about 50% of the time. I'm very sure that this is reproducible. I often get this to happen when I have a button in a UITableViewCell and I click on it while the table view is still scrolling.
Is there something wrong with the way I'm overriding the setHighlighted method in the subclass? This is my implementation:
#implementation SCPFormButton
- (id)initWithFrame:(CGRect)frame label:(NSString *)label
{
self = [super initWithFrame:frame];
if (self) {
UILabel *buttonLabel = [[UILabel alloc] init];
buttonLabel.attributedText = [[NSAttributedString alloc] initWithString:[label uppercaseString] attributes:kButtonLabelAttributes];
[buttonLabel sizeToFit];
buttonLabel.frame = CGRectMake(kMaxWidth / 2 - buttonLabel.frame.size.width / 2, kStandardComponentHeight / 2 - buttonLabel.frame.size.height / 2, buttonLabel.frame.size.width, buttonLabel.frame.size.height);
[self addSubview:buttonLabel];
self.backgroundColor = kFormButtonColorDefault;
}
return self;
}
- (void)setHighlighted:(BOOL)highlighted
{
self.backgroundColor = highlighted ? kFormButtonColorHighlighted : kFormButtonColorDefault;
[self setNeedsDisplay];
}
#end
I would try to call super in your setHighlighted override. Indeed, Apple docs for UIControl state:
Specify YES if the control is highlighted; otherwise NO. By default, a control is not highlighted. UIControl automatically sets and clears this state automatically when a touch enters and exits during tracking and when there is a touch up.
So, it seems there is some kind of state handling going on in UIControl associated with this.
If this does not help, I would try to add a log trace so you can check which state the button is in when the touch is handled.
You are missing the call to super. But, anyway, subclassing UIButton is not recommended, I would try to do it using setBackgroundImage:forState instead.

Size of bullets in UITextField with secureTextEntry changes size as focus switches when using custom font

I have a UITextField that is using the Museo Sans Rounded 300 font. Everything works fine for normal UITextFields, but when you set the secureTextEntry = YES, then there's this disconcerting change to the size of the bullets as the UITextField gets and loses focus (i.e. becomes, and relinquishes, being the first responder).
When the UITextField has focus, the bullets appear to be using the custom font, but once it loses focus they change to being these much bigger (standard size) bullets.
So, the only way I found to combat this was to use the textFieldDidBeginEditing and textFieldDidEndEditing delegate methods, keep track of what was entered in the text field, replace it with a mask of bullets, and disable secureTextEntry. So, when they leave the field, they’re actually just seeing the right number of bullets, rather than their secured text. It’s hacky and messy, but it’ll do for me, perhaps for you, too.
I found an easy solution an it works quite good.
Basically you have to change the font to a custom font when you set secureTextEntry to yes.
- (void)textFieldDidBeginEditing:(UITextField *)textField{
if([textField.text isEqual:#"Password"]){
textField.text = #"";
textField.font = [UIFont fontWithName:#"Helvetica" size:14.5];
textField.secureTextEntry = YES;
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
if([textField.text isEqual:#""]){
textField.text = #"Password";
textField.secureTextEntry = NO;
textField.font = [UIFont fontWithName:#"YourFont" size:14.5];
}
}
Another workaround:
While this is an iOS bug (and new in iOS 7, I should add), I do have another way to work around it that one might find acceptable. The functionality is still slightly degraded but not by much.
Basically, the idea is to set the font to the default font family/style whenever the field has something entered in it; but when nothing is entered, set it to your custom font. (The font size can be left alone, as it's the family/style, not the size, that is buggy.) Trap every change of the field's value and set the font accordingly at that time. Then the faint "hint" text when nothing is entered has the font that you want (custom); but when anything is entered (whether you are editing or not) will use default (Helvetica). Since bullets are bullets, this should look fine.
The one downside is that the characters, as you type before being replaced by bullets, will use default font (Helvetica). That's only for a split second per character though. If that is acceptable, then this solution works.
i just test result above, #Javier Peigneux's answer is the most concise
#pragma mark -- UITextFieldDelegate
- (void)textFieldDidBeginEditing:(UCSSafeTF *)safeTF{
safeTF.font = [UIFont fontWithName:#"Helvetica" size:14];
}
- (void)textFieldDidEndEditing:(UCSSafeTF *)safeTF{
safeTF.font = [UIFont fontWithName:#"Helvetica" size:14];
}
now i write like this, and the result is OK. then the reason why you see the bullets size change from small to big is very clear, just because apple iOS 10 below "help" us resize the custom font. hope will help you .
Just create a method that gets called every time the show/hide password toggle is selected. Inside the method, set the font to nil, then set the font to your custom font and font size. You should be setting the custom font and size in the viewWillAppear method as well. Inside this method, you're re-setting it.
This way, you don't need to disable secureTextEntry(which could make your text field vulnerable) and you don't need to use textFieldDidBeginEditing or textFieldDidEndEditing.
Code Example:
//if the password is obscured and the toggle to show it has been turned on, display password. Else, obscure it.
- (IBAction)togglePasswordVisibility:(id)sender {
// Xcode contains a bug where the font changes to default font if these two lines of code are not included.
self.passwordInputTextField.font = nil;
self.passwordInputTextField.font = [UIFont fontWithName:#"myCustomFontName" size:myDesiredFontSize]; //set this in viewWillAppear as well!
if (self.passwordInputTextField.secureTextEntry == YES) {
self.passwordInputTextField.secureTextEntry = NO;
[self.showHideButton setTitle:#"HIDE" forState:UIControlStateNormal];
} else {
self.passwordInputTextField.secureTextEntry = YES;
[self.showHideButton setTitle:#"SHOW" forState:UIControlStateNormal];
}
}

Memory management problem (release UIVIewCotroller)

I develop the game for iPad (composing image from puzzles). In my menu i choose level difficult (simple, medium or hard). After selecting the main playing field will be shown.
Here's place, where i create the main playing field:
- (void)simpleDiffButtonClicked:(id)sender
{
UIButton *button = sender;
if (simpleDiffButton == button) {
UIView *mySuperView = self.view.superview;
mainGame = [[MainGame alloc] initWithMode:1 andImage:nil]; //mainGame variable is declared in header file like: MainGame *mainGame;
mainGame.view.frame = CGRectMake(0, 0, 1024, 768);
[mySuperView addSubview: mainGame.view];
}
}
After this playing field is appears (there are a lot of sublayers adding to self.view.layer) and i can interact with it. When i want to quit from it, i click button "back". (here i want to release my viewcontroller)
- (void)backToMenuButtonClicked:(id)sender
{
UIButton *button = sender;
if (nextImageClick == YES) {
return;
}
if (backToMenuButton == button) {
self.view.layer.sublayers = nil; //here's an exception
[self.view removeFromSuperview];
}
}
After clicking "back" button everything is ok. And i can choose difficultly level again. A choose a level, and after it clicking "back" button again and at this place application crashes (EXC_BAD_ACCESS).
As i understand "self.view.layer.sublayers = nil" causes the exception.
Without it everything is ok. But memory is leaking. And after several minutes of playing app was crashes (memory warning 2).
I cannot solve the problem for about a week. I don't understand what to do to release my viewcontroller (or i need to release all sublayers in controller?).
Please, someone help me.
Thanks in advance.
Try to turn on NSZombieEnabled and check out Debugger and Console when it crush, it can give some more info about the problem.
P.S. NSZombieEnabled : http://www.cocoadev.com/index.pl?NSZombieEnabled (you may want to try useing .gdbinit).
P.P.S:
Btw, there might be some other problem in the line where "mainGame = [[MainGame alloc] initW...". -- where [mainGame release] is called? (it should be called as many as simpleDiffButtonClicked which allocs new instance of MainGame to mainGame variable (every time))

How do I disable a UIButton?

I am working on a project in which I have to show all photos of Photo Library in a plist and show them horizontally on UIButtons.
My app will also have an edit button: when the user clicks this button, a delete mark (such as usually appears in other iPhone/iPad apps) should show on each button.
But here's the crucial bit: as soon as this delete mark appears, the functionality of the button should be disabled. I've tried accomplishing this with the following:
{
editbutton.enabled=NO;
}
...but it neither produces an error nor works. What should I do?
Please set this...
editButton.userInteractionEnabled = NO;
or You can use
editButton.enabled = NO;
Swift 3 and above
editButton.isEnabled = false
setEnabled is now part of the setter method for isEnabled.
setter for property enabled is overridden in class UIButton. try to send a message.
[editbutton setEnabled:NO];
Use the enabled property of UIControl which the super class of UIButton and set it with NO.
myButton.enabled = NO;
You could also try as #Marvin suggested,
In that case your button will not respond to any touch event from user,
In addition to the above:
Set
editButton.userInteractionEnabled = NO;
or you can use
editButton.enabled = NO;
You might want to gray out the button so the user knows it was disabled:
editButton.alpha = 0.66
yourBtn.userInteractionEnabled = NO;

Resources