Lomohome.com :: 괴발자 모근원

지난 포스트를 보면 웹뷰에서 자바스크립트 alert 을 웹뷰에서 재정의 해서 썼는데
개발을 하다가 난관에 부딫혔다. 자바스크립트의 alert 말고, confirm 을 사용할때에도 재정의가 필요해졌다.

confirm 창은 특성상, '예','아니오' 버튼이 나오고 이 버튼이 눌리면 버튼에 따라 액션을 달리 취해주어야한다.

그런데 UIAlertView 를 show 하게 되면 예, 아니오 버튼과 상관없이 밑의 코드가 주~욱 실행되버려서 예,아니오의 리턴값을 받을수가 없다. (말로 표현하자니.. 이거 영..)


억지로 버튼을 누르기전까지 루프를 돌려서 지연을 시키고, UIAlertView 가 사라지는 시점에 버튼의 결과를 가지고와서 처리하는것으로 변경한 코드.
분명 더 좋은 방법이 있을것 같은데 ㅠ 못찾겠다.

*헤더부분은 생략.

//@Geunwon,Mo 2010.9.17 : UIWebView Javascript alert 위한 카테고리.

@implementation UIWebView (JavaScriptAlert)

.... 저번포스트 생략 ....

static BOOL diagStat = NO; //예,아니오 버튼의 상태를 저장할 임시 변수

- (BOOL)webView:(UIWebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame{

NSLog(@"javascript ConfirmPanel : %@",message);

UIAlertView *confirmDiag = [[UIAlertView alloc] initWithTitle:nil message:message delegate:self cancelButtonTitle:NSLocalizedString(@"Yes", @"") otherButtonTitles:NSLocalizedString(@"No", @"아니오"), nil];

[confirmDiag show];

//버튼 누르기전까지 지연.

while (confirmDiag.hidden == NO && confirmDiag.superview != nil)

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01f]];

[confirmDiag release];

return diagStat;

}



//요놈은 UIAlertViewDelegate 를 구현하여 버튼이 눌렸을때 실행될 메소드

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{

//index 0 : YES , 1 : NO

if (buttonIndex == 0){

//return YES;

diagStat = YES;

} else if (buttonIndex == 1) {

//return NO;

diagStat = NO;

}

}

@end


동작순서는 웹뷰에서 confirm 자바스크립트 함수가 호출이 되면 카테고리로 구현한 webView: runJavaScriptConfirmPanelWithMessage 메소드가 호출이되고,
UIAlertView 로 메세지창(+예,아니오)을 띄우고 while 문을 통하여 메세지 창이 없어질때까지 루프..;;
그리고 메세지창에서 버튼을 누르면 alertView: clickedButtonAtIndex 메소드가 호출이 되고 미리 준비해둔 전역변수에 버튼에 따라 상태값을 저장.
메세지창이 닫히면서 while 루프가 끝나게 되고 전역변수의 값을 자바스크립트로 리턴. 하게된다.


* 더 좋은 방법이 있으시면 공유 부탁드립니다. ㅠㅠ
저작자 표시 비영리 변경 금지
신고
Posted by Geunwon Mo 모근원
  1. 형~ 저 병돈입니다 ㅋㅋ
    오랜만에 형 생각나서 구글에 형 이름 쳤더니 일로 인도하더군요 ~~ ㅋ
    20page까지 역주행으로 잘봤습니다 ~ㅋ
    종종 와서 좋은 사진 보고 갈게요 ㅋ

  2. 비밀댓글입니다

  3. 좋은 정보네요~ 감사합니다 많은 도움이 되었어요

  4. 좋은 정보네요.ㅎ 필요했는데...감사합니다. 출처 명시하고 퍼가도록 하겠습니다^^; 문제되면, 제 블로그에 말씀부탁드리겠습니다. 감사합니다~

  5. 흠 여쭤볼게 있는데요.. UIWebView+WebController.m 과 같이 해서 카테고리화해주고 말씀하신것 처럼 하면 alert을 이제 형태를 자유자재로 만들수 있게 되었습니다. 하지만 alert의 메세지(message) 자체를 WebController.m 에 있는 함수에 인자로 넘겨줄려면 어떻게 해야 하나요?
    [sender.delegate getdata:message]; 와 같은건 통하질 않네요...
    제가 초보인지라 셀렉터, 상호 정보 전달 등이 많이 개념이 꼬여있어요.. 그래도 조금 도움 부탁드릴게요. 감사합니다.

    • 제가 질문을 제대로 이해했는지 모르겠지만..
      쉽게 생각하시면 될것 같습니다.

      - (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame;

      함수 등에서 받은 message 를 전역변수(또는 static)에 넣어서 다른 메소드에서 사용하거나
      [self performSelector:@selector(aaa:) withObject:message];
      등의 메소드를 사용해서 함수에 직접 넘겨주거나 하시면 될것 같습니다.

  6. 미련곰탱이 2011.11.28 14:47 신고

    java-confirm에서 uialertview에서 리턴값을 어찌 받아와야 할지 모르던차에 검색해서 덕분에 해결했네요.감사합니다

  7. 정말 훌륭한 팁이 아닐 수 없네요.
    이 팁이 아니었다면 정말 끔직합니다.
    감사합니다.

  8. 에르타이 2012.06.14 10:07 신고

    UIAlertView 대기하기 찾다보니 들어왔네요.
    글 쓰신대로 잠깐 해봤다가 더 좋은 방법이 없나 찾아보니, UIAlertView도 delegate가 있더라고요.
    UIAlertView에서 delegate를 적당한 녀석으로 정해주고, 다음과 같은 녀석을 정해주면 되네요.
    - ( void ) alertView:( UIAlertView * ) alertView clickedButtonAtIndex:( NSInteger ) buttonIndex
    이렇게 하면 버튼 누르면 이쪽으로 와서 처리가 가능하네요.

    물론 처리 순서를 다시 정해줘야 한다는 단점은 있지만, 무한 대기 시키는 것보다는 조금 나아보입니다.
    이 댓글을 쓰는 때에는 이미 아셨을지도 모르겠네요. ^^

    • 답변 감사합니다 ^^
      - ( void ) alertView:( UIAlertView * ) alertView clickedButtonAtIndex:( NSInteger ) buttonIndex
      는 위의 본문에서도 사용하고 있는 델리게이트입니다.
      통상의 UIAlertView 의 버튼 액션은 이곳에서 해주는게 당연하지만
      위의 경우엔 webview 에서 javascript 의 confirm 창이라는 함정이 있습니다;;
      그래서 저런 꼼수를 썻는데 다시 보니 수정할곳이 많군요.
      워낙 오래전에 만든거라.
      tag 도 안쓰여있구요..
      무한대기보다 분명 좋은 방법이 생길듯 합니다.
      iOS6 에서 webView 에 대대적인 수정이 있는듯 합니다.
      올라가면 생각해보죠 뭐 ㅋ
      감사합니다 ^^

  9. 감사합니다 ~