2012-03-06 3 views
1

이것은 내게 약간의 배트를 안겨주고 내 눈은 반짝 거립니다.iOS에서보기를로드 할 때의 이벤트 순서

내비게이션 컨트롤러가있는 앱이 있습니다.

보기 A는 일부 입력 필드가 있고 내가 그 이벤트의 결과로 탐색 컨트롤러의 왼쪽 상단에있는 "뒤로"버튼을 탭하면 순서로 해고보기 B

로드 "계속"버튼을 I

내 추적이 밝혀/이해를 ... 기대하지 않고있어

View B: viewWillDisappear 
View A: viewWillAppear 
View B: textFieldShouldEndEditing 

편집 - 자세한 내용/코드 설명 내 이전 막연한 질문

개념적으로 다음 접근 방식이 잘 작동하고 몇 차례의 품질 보증 테스트를 통과했습니다.

요약하면 텍스트 필드의 유효성을 검사하기 위해 textFieldShouldEndEditing을 사용하고 있습니다. 유효하지 않은 경우 필드에 초점을 맞추고 잘못된 메시지를 표시합니다. 사용자가 필드에서 필드로 이동하려고하면 모두 유효하며 유효성 검사가 작동합니다.

아래 코드에서 문제가되는 조건은 부분 값을 입력 한 다음 뒤로를 클릭하는 경우입니다. 전체 앱에있는 UITextFields 전체 고정 (입력 허용 안함) 및 경우에 따라 앱이 다운됩니다.

초기 질문을 게시하도록 유도 한 접근 방식은 비공개를 만드는 것이 었습니다. BOOL isDisappearing;

내가 확인할 수있는 viewWillDisappear (대부분의 경우 textFieldShouldEndEditing보다 먼저 발생 함), YES이면 UITextFields/app을 실행하고 멈추는 문제가있는 코드를 누전시킵니다.

이것은 몇 가지보기에서 제대로 작동하지만 아래의 textFieldShouldEndEditing (보기 B) 전에 'VIEW A : viewWillAppear'이벤트가 발생하는 경우 - isDisappearing이 어떻게 든 '아니오'로 설정되고 문제 코드가 실행 중입니다. textFieldShouldEndEditing

나는 이것이 도움이되기를 바랍니다. 코드 없이는 설명하기가 어렵습니다. 그러나 관련성이있는 부분까지 정리하려고했습니다. 나는 이것이 이곳에서 적절하기를 바란다. 나는 지역 사회에 새로운 사람들이다. VIEW B에 대한

코드 :

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)rangereplacementString:(NSString *)string 
{ 
    // Enforce max lengths 
    // The return key from the keyboard counts as a character, so we have to exempt it 
if (textField.tag == ROUTING_NUMBER_TAG) 
{ 
    NSUInteger newLength = [textField.text length] + [string length] - range.length; 
    return (newLength > 9 && ![string isEqualToString:@"\n"]) ? NO : YES;   
} 
else if (textField.tag == ACCOUNT_NUMBER_TAG) 
{ 
    NSUInteger newLength = [textField.text length] + [string length] - range.length; 
    return (newLength > 17 && ![string isEqualToString:@"\n"]) ? NO : YES;   
} 
return YES; 
} 

// textField validation 
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField 
{ 
if (isDisappearing) 

    return YES; 

//run fields through validators and display validation messages. 
//IF THEY DON’T PASS VALIDATION IM "HOLDING THEM HOSTAGE" BY KEEPING THE FOCUS ON THE UITEXTFIELD (returning NO) 

if (textField.tag == ROUTING_NUMBER_TAG) 
{ 
    if ([Utility isValidRoutingNumber:textField.text]== NO) 
    { 
     [[iToast makeText:NSLocalizedString(@"Enter valid routing number", @"")] show]; 
     return NO; 
    } 
    else 
    { //save it 
     extension.payment.routingNumber = routingNumber.text; 
    } 
} 
else if (textField.tag == ACCOUNT_NUMBER_TAG) 
{ 
    if ([Utility isValidAccountNumber:textField.text] == NO) 
    { 
     [[iToast makeText:NSLocalizedString(@"Enter valid account number", @"")] show]; 
     return NO; 
    } 
    else 
    { //save it 
     extension.payment.accountNumber = accountNumber.text; 
    } 
} 
return YES; 
} 


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

//I do nothing here except nulling out the 'activefield' var I use to autoscroll the uiscrollview as the user taps around from field to field 

} 



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

//reset the bool so that when they come back we're back to the 'normal' state and validation will again be checked in textFieldShouldEndEditing 

isDisappearing = NO; 
} 

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


-(void)viewWillDisappear:(BOOL)animated 
{ 
TRC_ENTRY 
//set the bool to bypass validations in textFieldShouldEndEditing 

isDisappearing = YES; 
[super viewWillDisappear:animated]; 
} 

답변

2

메시지의 순서가 명확하게 정의되거나 이름에 강하게 암시되는 경우를 제외하고 특정 순서에 따라 피해야합니다. 예를 들어 어떤보기에서 -viewDidAppear보다 먼저 -viewWillAppear이 호출 될 것으로 예상 할 수 있지만 다른보기로 보낸 메시지와 관련하여 특정보기에서 하나의보기 -viewWillAppear이 호출되지는 않습니다.

주문에 의존하지 않고 특정 기능을 구현하는 방법을 찾는 데 도움이 필요하면 질문하십시오. 그러나 호출의 순서가 메서드 이름에서 문서화되거나 뻔뻔스럽게 명백한 경우가 아니면 특정 순서를 기대하지 마십시오.

업데이트 : 내가 정확히 무엇을 당신이 추가 한 코드에 잘못된거야 볼 수 없지만, 아마도 몇 가지 제안이 도움이 될 것입니다 :

  1. 당신의 뷰 컨트롤러의 인스턴스 변수 귀하의 isDisappearing 변수, 전역 변수, 또는 무엇? 인스턴스 변수 인 경우 어떻게 변경되는지 파악하십시오. 그것이 글로벌 변수라면, 음 ... 그렇게하지 마십시오.

  2. warning in the docs-textViewShouldEndEditing:이 권고 사항이며 결과가 무엇이든 상관없이보기가 편집을 중단 할 수 있다는 점을 유의하십시오.

  3. iToast 항목을 임시로 삭제 해보세요. 충돌이 여전히 발생하면 적어도 문제의 원인으로이를 제거했습니다. 그런 일이 없으면 검색 범위가 좁아집니다.

  4. 크래시의 원인을 확인하십시오. (이것은 실제로 처음에 목록에 나와야합니다.) 충돌은 단지 신비하게 발생하지 않습니다. 충돌이 일어나는 이유가 있습니다. 그 이유를 찾으면 85 % 완료됩니다. 충돌이 발생할 때 스택 추적을 검사하여 시작하십시오. 그것이 충분한 단서를 제공하지 못한다면, 충돌을 일으키는 라인 앞에 어딘가에 중단 점을 배치하고 충돌 할 때까지 스테핑을 시작하십시오. 다른 모든 방법이 실패하면 로깅 메시지를 시작하여 실행을 추적하고 가정을 모니터링하십시오.

  5. 귀하의보기 컨트롤러 A가 정확하게 -viewWillAppear 방법으로 수행하고 있습니까? 그것이 문제의 일부가 될 수 있습니까? 대신 코드를 -viewDidAppear으로 옮길 수 있습니까?

+0

실수로 내 의견을 성급하게 저질렀습니다. 다시 시도하자 ... 내 문제는 UITextFieldDelate 관련 이벤트가 예기치 않게 발생하는 것 같습니다. 논리적 인 이유가 있지만 어떤 경우에는 UITextField에 포커스가있는 동안 NavController "뒤로"버튼을 클릭 할 때만 textFieldShouldEndEditing * 만 실행됩니다. 이 시나리오의 코드가 작동합니다. 난 그냥 textFieldDidEndEditing 또한 문제가 발생하는 경우 발사 발견했습니다. 나는 지금 왜이 특별한 경우에 DID가 발사되고 다른 것들은 발사되지 않는지 알아 내려고하고있다. – jaySF

+0

@jayboston'-textFieldShouldEndEditing :'은 텍스트 필드가 '첫 번째 응답자'상태를 포기할 때마다 호출되어야합니다. 따라서 다른 텍스트 필드를 탭하면 현재 포커스 된 텍스트 필드가 호출되어야합니다. 그렇지 않으면 텍스트 필드가 첫 번째 응답자가되는 것을 중지시키는 다른 작업을 수행해야합니다. 이것은 분명히 '뒤로'버튼을 누르는 것을 포함합니다. 첫 번째 응답자를 포함하여 응답자 체인의 상당 부분을 대체 할 것이기 때문입니다. 텍스트 필드가 최초 응답자가 분명히 중단되었을 때'-textFieldDidEndEditing :'이 * 호출 *되지 않는 경우가 있습니까? – Caleb

+0

@jayboston 또한 동일한 델리게이트로 둘 이상의 텍스트 필드가있는 경우 해당 객체는 모든 텍스트 필드에 대한 메시지를 수신합니다. 따라서 하나의 필드에 대해서는'-textFieldShouldBeginEditing :'을, 다른 필드에 대해서는'-textFieldDidEndEditing :'을 얻을 수 있습니다. 'sender' 매개 변수에주의를 기울이십시오. – Caleb

0

뷰 B viewWillDisappear에 [self.youTextField resignFirstResponder]을 수행하십시오.

0

이 질문에 직접적으로 관련되지 않을 수도 있습니다,하지만 당신은 당신이 완전하지 뷰의 수명을 이해하고 느끼는 경우, 여기를 살펴 보시기 바랍니다 : What is the process of a UIViewController birth (which method follows which)?

그것은 좋은 설명입니다.

+0

감사합니다. 뷰 라이프 사이클을 꽤 잘 이해했습니다. textField 이벤트가 발생했을 때 나타나는 문제입니다. UITextFieldDelegate를 사용하고 있고 해당 이벤트에서 많은 필드 유효성 검사를 처리하고 있습니다. – jaySF

관련 문제