Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

ios - I receive EXC_BAD_ACCESS using custom UITextField. How to trace the issue?

I am writing App for iOS 6 and 7 which will be running iPhone and iPad. The presentation of controls force me to use custom UITextField class - I need to have indent of the text (I have 2 text fields with images inside) and I need to change border colour of currently edited text box.

I find on the internet examples and create the following class:

In the interface:

#import <QuartzCore/QuartzCore.h>
#import <Foundation/Foundation.h>

@interface PEStfCustomTextField : UITextField<UITextFieldDelegate>
@property (nonatomic) int maxSymbols;
@property (nonatomic) int leftIndent;
@end

In the implementation:

#import <QuartzCore/QuartzCore.h>
#import "PEStfCustomTextField.h"

@implementation PEStfCustomTextField

//- (id)initWithFrame:(CGRect)frame
//{
//    if (self = [super initWithFrame:frame]) {
//        self.delegate = self;
//    }
//    return self;
//}

#pragma mark methods
// ------------------------------------------------------

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{

    // Change border of text field that is editing to orange
    textField.layer.masksToBounds=YES;
    textField.layer.borderColor=[[UIColor orangeColor] CGColor];
    textField.layer.borderWidth= 1.0f;

    UIView *spacerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _leftIndent, 10)];
    [self setLeftViewMode:UITextFieldViewModeAlways];
    [self setLeftView:spacerView];

    return YES;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField{
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{

    // Change border of text field that is edited to black
    textField.layer.masksToBounds=YES;
    textField.layer.borderColor=[[UIColor blackColor] CGColor];
    textField.layer.borderWidth= 1.0f;

    return YES;
}

- (void)textFieldDidEndEditing:(UITextField *)textField{
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

    // Restrict number of symbols in text field to "maxSymbols"
    NSUInteger oldLength = [textField.text length];
    NSUInteger replacementLength = [string length];
    NSUInteger rangeLength = range.length;

    NSUInteger newLength = oldLength - rangeLength + replacementLength;

    BOOL returnKey = [string rangeOfString: @"
"].location != NSNotFound;

    return newLength <= (int)_maxSymbols || returnKey;
}

- (BOOL)textFieldShouldClear:(UITextField *)textField{
    return YES;
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    return YES;
}
// ------------------------------------------------------

#pragma mark inits
// ------------------------------------------------------
// Custom init
- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {

        self.layer.borderColor=[[UIColor grayColor] CGColor];
        self.delegate = self;
    }
    return self;
}

// ------------------------------------------------------

@end

I have 3 fields which are only text and they work fine. In other view controller I have another 2 text fields which can be filled with any text. When I start filling them on 2nd or 3rd or 4th letter filled I receive EXC_BAD_ACCESS (code=2, address=0xbf7ffffc).

I have the outlet for each of the field: @property (weak, nonatomic) IBOutlet PEStfCustomTextField *txtCustom;

I initialise text field:

_txtCustom.maxSymbols = 15;
_txtCustom.leftIndent = 10;

I look at the code and initialisation looks fine to me. Can you tell me how to find and fix the problem? I have no idea where the problem is coming from.

EDIT: Trace from stack ...

* thread #1: tid = 0x4af98, 0x0182e0b4 libobjc.A.dylib`lookUpImpOrForward + 9, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0xbf7ffffc)
    frame #0: 0x0182e0b4 libobjc.A.dylib`lookUpImpOrForward + 9
    frame #1: 0x0182e05c libobjc.A.dylib`lookUpImpOrNil + 62
    frame #2: 0x0182584a libobjc.A.dylib`class_respondsToSelector_inst + 65
    frame #3: 0x0183846d libobjc.A.dylib`-[NSObject respondsToSelector:] + 58
    frame #4: 0x00c0a7dc UIKit`-[UITextField respondsToSelector:] + 58
    frame #5: 0x00c0f1a1 UIKit`-[UITextField customOverlayContainer] + 55
    frame #6: 0x00c0f1b4 UIKit`-[UITextField customOverlayContainer] + 74
    frame #7: 0x00c0f1b4 UIKit`-[UITextField customOverlayContainer] + 74
... (this row appears many times) ...
    frame #261721: 0x00c0f1b4 UIKit`-[UITextField customOverlayContainer] + 74
    frame #261722: 0x00c0f1b4 UIKit`-[UITextField customOverlayContainer] + 74
    frame #261723: 0x00c060a6 UIKit`-[UITextField automaticallySelectedOverlay] + 36
    frame #261724: 0x006da666 UIKit`-[UIKeyboardImpl inputOverlayContainer] + 459
    frame #261725: 0x006dbdf2 UIKit`-[UIKeyboardImpl _autocorrectPromptRects] + 563
    frame #261726: 0x006dc02f UIKit`-[UIKeyboardImpl updateAutocorrectPrompt:] + 390
    frame #261727: 0x006dbb15 UIKit`-[UIKeyboardImpl updateAutocorrectPromptAction] + 143
    frame #261728: 0x0183882b libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
    frame #261729: 0x00685469 UIKit`-[UIDelayedAction timerFired:] + 83
    frame #261730: 0x0145cde7 Foundation`__NSFireTimer + 97
    frame #261731: 0x01a65ac6 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
    frame #261732: 0x01a654ad CoreFoundation`__CFRunLoopDoTimer + 1181
    frame #261733: 0x01a4d538 CoreFoundation`__CFRunLoopRun + 1816
    frame #261734: 0x01a4c9d3 CoreFoundation`CFRunLoopRunSpecific + 467
    frame #261735: 0x01a4c7eb CoreFoundation`CFRunLoopRunInMode + 123
    frame #261736: 0x03ab65ee GraphicsServices`GSEventRunModal + 192
    frame #261737: 0x03ab642b GraphicsServices`GSEventRun + 104
    frame #261738: 0x004e6f9b UIKit`UIApplicationMain + 1225
  * frame #261739: 0x000538bd PA-PAY`main(argc=1, argv=0xbfffed68) + 141 at main.m:16

I suppose that there are some infinite loop, but I can not figure out why. One thing that I noticed - when I fill data from keyboard in simulator I did not receive the exception. May be this is connected with code for hiding keyboard.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is that you set the object as its own delegate. This is not recommended for UITextFields. If you don't like to have the delegate code in your view controllers, as an alternative, you could put the code in a separate delegate class.

If you still want to go with your approach, you can add the following methods to fix the problem:

- (id)customOverlayContainer {
    return self;
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    return [self applySimpleMaskOnTextfield:textField range:range replacementString:string];
}

The customOverlayContainer method is undocumented by Apple, so it might get your app rejected.

Also see here and here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...