Ich bekomme ein seltsames Verhalten mit presentViewController:animated:completion
. Was ich mache, ist im Wesentlichen ein Ratespiel.
Ich habe einen UIViewController
(frequenzViewController), der einen UITableView
(frequenzTableView) enthält. Wenn der Benutzer auf die Zeile in questionTableView tippt, die die richtige Antwort enthält, sollte eine Ansicht (korrektViewController) instanziiert und ihre Ansicht als modale Ansicht vom unteren Bildschirmrand nach oben verschoben werden. Dies teilt dem Benutzer mit, dass er eine richtige Antwort hat, und setzt den dahinter liegenden frequenzViewController für die nächste Frage zurück. Der korrekte ViewController wird auf Knopfdruck geschlossen, um die nächste Frage anzuzeigen.
Dies alles funktioniert jedes Mal korrekt und die Ansicht des korrekten ViewControllers wird sofort angezeigt, solange dies der Fall presentViewController:animated:completion
ist animated:NO
.
Wenn ich setze animated:YES
, wird korrekter ViewController initialisiert und ruft auf viewDidLoad
. Allerdings viewWillAppear
, viewDidAppear
und der Abschluss - Block aus presentViewController:animated:completion
nicht aufgerufen werden . Die App sitzt nur da und zeigt immer noch den Frequenz-ViewController an, bis ich ein zweites Mal tippe. Jetzt werden viewWillAppear, viewDidAppear und der Abschlussblock aufgerufen.
Ich habe ein bisschen mehr nachgeforscht, und es ist nicht nur ein weiterer Tipp, der dazu führt, dass es weitergeht. Wenn ich mein iPhone neige oder schüttle, kann dies auch dazu führen, dass es viewWillLoad usw. auslöst. Es ist, als würde es auf andere Benutzereingaben warten, bevor es fortschreitet. Dies geschieht auf einem echten iPhone und im Simulator, was ich durch Senden des Shake-Befehls an den Simulator bewiesen habe.
Ich bin wirklich ratlos, was ich dagegen tun soll ... Ich würde mich über jede Hilfe freuen, die jemand leisten kann.
Vielen Dank
Hier ist mein Code. Es ist ziemlich einfach ...
Dies ist Code in questionViewController, der als Delegat für questionTableView fungiert
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row != [self.frequencyModel currentFrequencyIndex])
{
// If guess was wrong, then mark the selection as incorrect
NSLog(@"Incorrect Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
UITableViewCell *cell = [self.frequencyTableView cellForRowAtIndexPath:indexPath];
[cell setBackgroundColor:[UIColor colorWithRed:240/255.0f green:110/255.0f blue:103/255.0f alpha:1.0f]];
}
else
{
// If guess was correct, show correct view
NSLog(@"Correct Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
self.correctViewController = [[HFBCorrectViewController alloc] init];
self.correctViewController.delegate = self;
[self presentViewController:self.correctViewController animated:YES completion:^(void){
NSLog(@"Completed Presenting correctViewController");
[self setUpViewForNextQuestion];
}];
}
}
Dies ist der gesamte korrekte ViewController
@implementation HFBCorrectViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
NSLog(@"[HFBCorrectViewController initWithNibName:bundle:]");
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"[HFBCorrectViewController viewDidLoad]");
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"[HFBCorrectViewController viewDidAppear]");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)close:(id)sender
{
NSLog(@"[HFBCorrectViewController close:sender:]");
[self.delegate didDismissCorrectViewController];
}
@end
Bearbeiten:
Ich habe diese Frage früher gefunden: UITableView und presentViewController benötigen 2 Klicks, um angezeigt zu werden
Und wenn ich meinen didSelectRow
Code in diesen Code ändere , funktioniert es sehr schnell mit Animationen ... Aber es ist chaotisch und macht keinen Sinn, warum es überhaupt nicht funktioniert. Also zähle ich das nicht als Antwort ...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row != [self.frequencyModel currentFrequencyIndex])
{
// If guess was wrong, then mark the selection as incorrect
NSLog(@"Incorrect Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
UITableViewCell *cell = [self.frequencyTableView cellForRowAtIndexPath:indexPath];
[cell setBackgroundColor:[UIColor colorWithRed:240/255.0f green:110/255.0f blue:103/255.0f alpha:1.0f]];
// [cell setAccessoryType:(UITableViewCellAccessoryType)]
}
else
{
// If guess was correct, show correct view
NSLog(@"Correct Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
////////////////////////////
// BELOW HERE ARE THE CHANGES
[self performSelector:@selector(showCorrectViewController:) withObject:nil afterDelay:0];
}
}
-(void)showCorrectViewController:(id)sender
{
self.correctViewController = [[HFBCorrectViewController alloc] init];
self.correctViewController.delegate = self;
self.correctViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:self.correctViewController animated:YES completion:^(void){
NSLog(@"Completed Presenting correctViewController");
[self setUpViewForNextQuestion];
}];
}
quelle
presentViewController:
die ausgelöst werden soll, mit einer großen Verzögerung beginnt. Dies scheint ein Fehler in iOS 7 zu sein und wird auch in den Apple Dev Forums behandelt.Antworten:
Ich bin heute auf das gleiche Problem gestoßen. Ich habe mich mit dem Thema befasst und es scheint, dass es damit zusammenhängt, dass der Haupt-Runloop schläft.
Eigentlich ist es ein sehr subtiler Fehler, denn wenn Sie die geringste Feedback-Animation, Timer usw. in Ihrem Code haben, tritt dieses Problem nicht auf, da der Runloop von diesen Quellen am Leben erhalten wird. Ich habe das Problem durch die Verwendung eines gefunden, auf
UITableViewCell
dasselectionStyle
gesetzt wurdeUITableViewCellSelectionStyleNone
, sodass keine Auswahlanimation den Runloop auslöste, nachdem der Zeilenauswahl-Handler ausgeführt wurde.Um das Problem zu beheben (bis Apple etwas unternimmt), können Sie den Haupt-Runloop auf verschiedene Arten auslösen:
Die am wenigsten aufdringliche Lösung besteht darin, Folgendes anzurufen
CFRunLoopWakeUp
:Oder Sie können einen leeren Block in die Hauptwarteschlange einreihen:
Es ist lustig, aber wenn Sie das Gerät schütteln, wird auch die Hauptschleife ausgelöst (es muss die Bewegungsereignisse verarbeiten). Das Gleiche gilt für Taps, aber das ist in der ursprünglichen Frage enthalten :) Wenn das System die Statusleiste aktualisiert (z. B. die Uhr aktualisiert, die WLAN-Signalstärke ändert sich usw.), wird auch die Hauptschleife aufgeweckt und die Ansicht angezeigt Regler.
Für alle Interessierten habe ich ein minimales Demonstrationsprojekt des Problems geschrieben, um die Runloop-Hypothese zu überprüfen: https://github.com/tzahola/present-bug
Ich habe den Fehler auch Apple gemeldet.
quelle
Überprüfen Sie dies: https://devforums.apple.com/thread/201431 Wenn Sie nicht alles lesen möchten, bestand die Lösung für einige Leute (einschließlich mich) darin, den
presentViewController
Anruf explizit im Hauptthread zu tätigen :Swift 4.2:
Ziel c:
Wahrscheinlich bringt iOS7 die Threads durcheinander
didSelectRowAtIndexPath
.quelle
Ich habe es in Swift 3.0 mit dem folgenden Code umgangen:
quelle
present
einen Schließungsrückruf anrief .Das Aufrufen
[viewController view]
des vorgestellten View Controllers hat mir geholfen.quelle
Ich wäre gespannt was
[self setUpViewForNextQuestion];
macht.Sie können versuchen,
[self.correctViewController.view setNeedsDisplay];
am Ende Ihres Abschlussblocks anzurufenpresentViewController
.quelle
Correct Guess: 1 kHz 18:04:57.173 Frequency[641:60b] [HFBCorrectViewController initWithNibName:bundle:] 18:04:57.177 Frequency[641:60b] [HFBCorrectViewController viewDidLoad]
Jetzt passiert nichts mehr bis:18:05:00.515 Frequency[641:60b] [HFBCorrectViewController viewDidAppear] 18:05:00.516 Frequency[641:60b] Completed Presenting correctViewController 18:05:00.517 Frequency[641:60b] [HFBFrequencyViewController setUpViewForNextQuestion]
Ich habe eine Erweiterung (Kategorie) mit einer Methode für UIViewController geschrieben, die das Problem löst. Vielen Dank an AX und NSHipster für die Implementierungshinweise ( swift / objectiv-c ).
Schnell
Ziel c
quelle
Überprüfen Sie, ob Ihre Zelle im Storyboard Auswahl = keine hat
Wenn ja, ändern Sie es in blau oder grau und es sollte funktionieren
quelle
XCode Vesion: 9.4.1, Swift 4.1
In meinem Fall passiert dies, wenn ich auf Zelle tippe und zur anderen Ansicht wechsle. Ich debugge in die Tiefe und es scheint, dass im Inneren passieren,
viewDidAppear
weil folgenden Code enthältdann habe ich oben das Code-Segment hinzugefügt
prepare(for segue: UIStoryboardSegue, sender: Any?)
und arbeite perfekt.Nach meiner Erfahrung lautet meine Lösung: Wenn wir hoffen, neue Änderungen (z. B. erneutes Laden der Tabelle, Deaktivieren der ausgewählten Zelle usw.) für die Tabellenansicht vorzunehmen, wenn Sie wieder aus der zweiten Ansicht zurückkehren, verwenden Sie delegate anstelle des
viewDidAppear
obigentableView.deselectRow
Codes Segment vor dem Verschieben des zweiten Ansichtsreglersquelle