2012-06-14 16 views
6

Tworzę UIActionSheet w actionSheet: clickButtonAtIndex delegate method.UIActionSheet trwa długo odpowiedź:

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex  
if(buttonIndex == 1){ 

     [self.myFirstView removeFromSuperview]; 

     if (!self.mySecondView) { 
      [[NSBundle mainBundle] loadNibNamed:@"MySecondView" owner:self options:nil]; 
     } 
     [self.mySecondView setFrame:CGRectMake(0, 0, 320, 480)]; 

     [[UIApplication sharedApplication].keyWindow addSubview: self.mySecondView]; 

     UIActionSheet * action = [[UIActionSheet alloc]initWithTitle:@"" 
                  delegate:self 
                cancelButtonTitle: nil 
               destructiveButtonTitle: deleteContacts 
                otherButtonTitles: cancel, nil]; 
     action.tag = 102; 
     [action showInView:self.view]; 
     [action release]; 

    } 

obsłużyć zdarzenia click tego UIActionSheet w dokładnie taki sam sposób jak powyżej.

if(actionSheet.tag == 102){ 

    if(buttonIndex == 0){ 
     if([[NSBundle mainBundle] loadNibNamed:@"MyThirdView" owner:self options:nil]) { 
      [self.myThirdView setFrame:CGRectMake(0, 0, 320, 480)]; 
      [[UIApplication sharedApplication].keyWindow addSubview:self.myThirdView]; 
     } 
     [self.mySecondView removeFromSuperview]; 

     [self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target]; 

     [self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0]; 

    } 
} 

Problem jestem stoi to tym, UIActionSheet zajmuje zbyt dużo czasu na odpowiedź. Kliknięcie przycisku UIActionSheet powoduje jego zatrzymanie na 2 lub 3 sekundy przed załadowaniem myThirdView. Nie jestem w stanie zrozumieć, jakie jest opóźnienie odpowiedzi w tym przypadku, ponieważ pierwszą czynnością w metodzie zdarzenia kliknięcia przycisku jest załadowanie myThirdView. Reszta kodu jest wykonywana tylko po kodzie do załadowania myThirdView. Ale nawet pierwsza linia kodu wydaje się wykonywać po opóźnieniu. Jakieś sugestie?

+0

to działa po zmianie '[działania showInView: self.view];' '[do działania showInView: self.mySecondView];'? – Felix

+0

To działa. Ale nie ma znaczącej zmiany w szybkości odpowiedzi arkusza działania. –

+0

Myślę, że właściwą odpowiedzią powinno być połączenie odpowiedzi Saada i Andrew Zimmera. Kod, który powinien być uruchomiony w wątku tła, jest linią kodu '[self.doneButton.target performSelector: self.doneButton.action withObject: self.doneButton];'. Reszta kodu, łącznie z metodą 'RemoveView' powinna działać w głównym wątku. Specjalne wyróżnienie dla Gabriela za symulację akcji dotykowej przycisku. –

Odpowiedz

2

Pytanie. Czy UIActionSheet zamarza, czy znika, a trzeci widok nie jest widoczny przez 2-3 sekundy?

Może to być spowodowane 1 z 2 problemów.

  1. Jeśli cała zamarza arkusza działania, a następnie robisz jakiś dźwiganie ciężarów, gdy init, że 3-te widok, ładujesz kilka podstawowych danych lub wiele aktywów, lub coś, co trwa bardzo długo. W takim przypadku musisz ponownie sformatować W JAKI sposób załadujesz ten trzeci widok. Sugerowałbym popychanie ciężkich ładunków w tle (to znaczy, jeśli masz dużo zdjęć w swoim Xib, może będziesz musiał załadować je w kodzie).

  2. Inną możliwością jest dodanie trzeciego widoku PONIŻEJ 2. widoku, a następnie nie ukrywanie drugiego widoku przez 3 sekundy (wykonując selektor z opóźnieniem). W takim przypadku po prostu usuń opóźnienie.

Zrobiłem kilka zajęć, aby pomóc mi wykonać egzekucje w czasie i znaleźć wąskie gardła w moim kodzie, wygląda na to, że mogą ci teraz pomóc. http://forrst.com/posts/Code_Execution_Timer_for_iOS_Development-dSJ

3

to być może z powodu tego

[self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0]; 

dokonać innego metod i zrobić to w taki sposób. jak to

[self viewRemover]; 

aw viewRemover

-(void) viewRemover 
{ 
    [self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0]; 

} 

tak Twój kod będzie tak teraz

if(actionSheet.tag == 102){ 

    if(buttonIndex == 0){ 
     if([[NSBundle mainBundle] loadNibNamed:@"MyThirdView" owner:self options:nil]) { 
      [self.myThirdView setFrame:CGRectMake(0, 0, 320, 480)]; 
      [[UIApplication sharedApplication].keyWindow addSubview:self.myThirdView]; 
     } 
     [self.mySecondView removeFromSuperview]; 

     [self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target]; 

    [self performSelectorInBackground:@selector(viewRemover) withObject:nil]; 

    } 
} 
+0

Wypróbowałem to. To nie działa. –

+0

Patrz zaktualizowane ans – Saad

+0

Zmieniono linię – Saad

3

akcje użytkowników interfejsu prowadzonych w głównym wątku i tylko wtedy, gdy kończy się twoja metoda. Tak więc, MyThirdView pojawi się dopiero po zakończeniu pozostałych instrukcji. Jedyną rzeczą, którą mogę zrozumieć opóźnia czyli:

[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target]; 

Jeśli robisz żadnych ciężkich obliczeń lub conection netto, na pewno to jest powód.

OTOH, myślę, że lepiej zmodyfikować ten wiersz:

[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton]; 

jeśli chcesz symulować działanie przycisku dotykowego.

+0

Nie wprowadzono żadnych znaczących różnic. –

1

Jak duży jest twój trzeci widok. jeśli plik nib musi zostać załadowany zbyt wiele, możesz czekać na dużo, jeśli musisz zmienić niektóre elementy interfejsu użytkownika i zablokować wątek interfejsu użytkownika, będziesz haolować swoją aplikację, aż upłynie limit czasu, a aplikacja zostanie przesunięta pewne rzeczy, aby zrekompensować ..

trasa biorę z tym jest dispatch_async i dispatch_sync

// This will release the UI thread which may be blocking your calls. 
// You can use any of the DISPATCH_QUEUE_PRIORITY_.... values to set how important this block is. 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
    // this command will get added to the stack and return without a hitch. 
    // the block will be run the next time the main runloop ends. 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // do some UI work that can happen without a hitch, and does not impact the calling block 
    }); 

    // this command will act much the same. but will pause the background execution 
    // of this block until the runloop has executed this and returned. 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     // do some UI work that must be completed to continue. 
    }); 

}); 

robi zbyt dużo w wątku UI będzie wstrzymać wykonywanie rzeczy, które się ułożone w kolejce. Przesłanie całego kodu do wątku w tle i tylko przeskoczenie do wątku interfejsu użytkownika, gdy trzeba zmienić interfejs użytkownika, jest lepszym i bardziej responsywnym sposobem kodowania aplikacji na iPhone'a.

Mam nadzieję, że to pomoże :)

+0

Ten blok kodu był dla mnie ratunkiem. UPEWNIJ SIĘ, ŻE NIE PONOWNIE AUTORELEASE PRZEDMIOTÓW. Ponieważ jest to blok, czasami czujesz, że możesz. –

+0

Obecnie używam łuku. Wierzę jednak, że blok zachowuje i uwalnia obiekty, które sam posiada. Czy to nie jest? –

+0

Nie jestem pewien, czy ma to miejsce, gdy używasz ARC, więc możesz być w porządku. Przekazywanie autoreleased obiektów pomiędzy wątkami jest raczej katastrofalne, jeśli nie jesteś w ARC. Spaliłem się przez to w przeszłości. –

Powiązane problemy