Ich habe diesen Absturzbericht erhalten, weiß aber nicht, wie ich ihn debuggen soll.
Fatal Exception NSInvalidArgumentException
Can't add self as subview
0 ... CoreFoundation __exceptionPreprocess + 130
1 libobjc.A.dylib objc_exception_throw + 38
2 CoreFoundation -[NSException initWithCoder:]
3 UIKit -[UIView(Internal) _addSubview:positioned:relativeTo:] + 110
4 UIKit -[UIView(Hierarchy) addSubview:] + 30
5 UIKit __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 1196
6 UIKit +[UIView(Animation) performWithoutAnimation:] + 72
7 UIKit -[_UINavigationParallaxTransition animateTransition:] + 732
8 UIKit -[UINavigationController _startCustomTransition:] + 2616
9 UIKit -[UINavigationController _startDeferredTransitionIfNeeded:] + 418
10 UIKit -[UINavigationController __viewWillLayoutSubviews] + 44
11 UIKit -[UILayoutContainerView layoutSubviews] + 184
12 UIKit -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 346
13 QuartzCore -[CALayer layoutSublayers] + 142
14 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*) + 350
15 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
16 QuartzCore CA::Context::commit_transaction(CA::Transaction*) + 228
17 QuartzCore CA::Transaction::commit() + 314
18 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 56
Die iOS-Version ist 7.0.3. Hat jemand diesen seltsamen Absturz erlebt?
AKTUALISIEREN:
Ich weiß nicht, wo in meinem Code dieser Absturz verursacht wurde, daher kann ich den Code hier leider nicht veröffentlichen.
Zweites UPDATE
Siehe die Antwort unten.
ios
iphone
objective-c
Arnol
quelle
quelle
Antworten:
Ich spekuliere basierend auf etwas Ähnlichem, das ich kürzlich getestet habe ... Wenn Sie einen Ansichts-Controller mit Animated: YES drücken (oder platzen lassen), wird er nicht sofort abgeschlossen, und schlimme Dinge passieren, wenn Sie vor der Animation einen weiteren Push oder Pop ausführen abgeschlossen. Sie können leicht testen, ob dies tatsächlich der Fall ist, indem Sie Ihre Push- und Pop-Vorgänge vorübergehend in Animiert: NEIN ändern (damit sie synchron abgeschlossen werden) und prüfen, ob der Absturz dadurch behoben wird. Wenn dies tatsächlich Ihr Problem ist und Sie die Animation wieder einschalten möchten, besteht die richtige Strategie darin, das UINavigationControllerDelegate-Protokoll zu implementieren. Dies umfasst die folgende Methode, die nach Abschluss der Animation aufgerufen wird:
Grundsätzlich möchten Sie nach Bedarf Code in diese Methode verschieben, um sicherzustellen, dass keine anderen Aktionen ausgeführt werden, die eine Änderung des NavigationController-Stapels verursachen könnten, bis die Animation abgeschlossen ist und der Stapel für weitere Änderungen bereit ist.
quelle
[newViewController setLabelTitle:...]
die Benutzeroberfläche des neuen View Controllers unmittelbar nach dem Aufruf von pushViewController mit änderte.Animated:YES.
Und ich löste das Verschieben der setLabelTitle-Methode nach viewDidLoad auf dem newViewController. Danke, dass du mir den Hinweis gegeben hast.Wir bekamen auch dieses Problem, und es war sehr wahrscheinlich, dass unser Problem durch dasselbe Problem verursacht wurde.
In unserem Fall mussten wir in einigen Fällen Daten aus dem Back-End abrufen, was bedeutete, dass ein Benutzer möglicherweise auf etwas tippte und es dann eine leichte Verzögerung gab, bevor der Navigations-Push auftrat. Wenn ein Benutzer schnell herum tippte, wurden möglicherweise zwei Navigationsschübe vom selben Ansichts-Controller ausgeführt, was genau diese Ausnahme auslöste.
Unsere Lösung ist eine Kategorie im UINavigationController, die Pushs / Pops verhindert, es sei denn, die oberste VC ist zu einem bestimmten Zeitpunkt dieselbe.
.h Datei:
.m Datei:
Bisher scheint dies das Problem für uns gelöst zu haben. Beispiel:
Grundsätzlich gilt die Regel: Bevor nicht benutzerbezogene Verzögerungen auftreten , nehmen Sie eine Sperre vom entsprechenden Navigationscontroller und nehmen Sie sie in den Aufruf zum Drücken / Pop auf.
Das Wort "Sperre" ist möglicherweise etwas schlecht formuliert, da es möglicherweise darauf hindeutet, dass eine Art Sperre stattfindet, die entsperrt werden muss. Da es jedoch nirgendwo eine "Entsperr" -Methode gibt, ist dies wahrscheinlich in Ordnung.
(Nebenbei bemerkt, "nicht benutzerbezogene Verzögerungen" sind alle Verzögerungen, die der Code verursacht, dh alles, was asynchron ist. Benutzer, die auf einen Navigationscontroller tippen, der animiert gedrückt wird, zählen nicht und es ist nicht erforderlich, die navigationLock: -Version für diese auszuführen Fälle.)
quelle
Dieser Code behebt das Problem: https://gist.github.com/nonamelive/9334458
Es verwendet eine private API, aber ich kann bestätigen, dass es App Store sicher ist. (Eine meiner Apps, die diesen Code verwenden, wurde vom App Store genehmigt.)
quelle
Ich werde weitere Details zu diesem Absturz in meiner App beschreiben und diese als beantwortet markieren.
Meine App verfügt über einen UINavigationController, wobei der Root-Controller ein UITableViewController ist, der eine Liste von Notizobjekten enthält. Das Notizobjekt hat eine Inhaltseigenschaft in HTML. Wählen Sie eine Notiz aus, um zum Detail-Controller zu gelangen.
Detail-Controller
Dieser Controller verfügt über eine UIWebView, in der der vom Root-Controller übergebene Noteninhalt angezeigt wird.
Dieser Controller ist der Delegat des Webview-Steuerelements. Wenn die Notiz Links enthält, tippen Sie auf einen Link, um zum In-App-Webbrowser zu gelangen.
Ich habe jeden Tag den obigen Absturzbericht erhalten. Ich weiß nicht, wo in meinem Code dieser Absturz verursacht wurde. Nach einigen Nachforschungen mit Hilfe eines Benutzers konnte ich diesen Absturz endlich beheben. Dieser HTML-Inhalt verursacht den Absturz:
In der viewDidLoad-Methode des Detail-Controllers habe ich diesen HTML-Code in das Webview-Steuerelement geladen. Unmittelbar danach wurde die oben genannte Delegate-Methode sofort mit request aufgerufen. URL ist die Quelle des Iframes (google.com). Diese Delegate-Methode ruft die pushViewController-Methode auf, während in viewDidLoad => Absturz!
Ich habe diesen Absturz behoben, indem ich den Navigationstyp überprüft habe:
Hoffe das hilft
quelle
viewDidLoad
?Ich hatte das gleiche Problem. Was für mich einfach funktionierte, war das Ändern von Animiert: Ja in Animiert: Nein.
Es sieht so aus, als ob das Problem darauf zurückzuführen ist, dass die Animation nicht rechtzeitig abgeschlossen wurde.
Hoffe das hilft jemandem.
quelle
Versuchen Sie, zwei Ansichts-Controller gleichzeitig zu drücken, um diesen Fehler zu reproduzieren. Oder gleichzeitig schieben und knallen. Beispiel:
Ich habe eine Kategorie erstellt, die diese Anrufe abfängt und sicher macht, indem sichergestellt wird, dass keine weiteren Pushs ausgeführt werden, während einer ausgeführt wird. Kopieren Sie einfach den Code in Ihr Projekt und schon können Sie loslegen.
quelle
popToRootViewController
oderpopToViewController:
wenn Sie sich bereits auf dem Root-View-Controller oder auf dem ViewController befinden, dieserdidShowViewController
nicht aufgerufen wird und er nicht mehr funktioniertviewTransitionInProgress
.self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController; [self.interactivePopGestureRecognizer setEnabled:YES];
Wann wurde der Erkenner deaktiviert? Und woher wissen Sie, was der Delegierte sein sollte? Mit diesen Zeilen bricht es für mich die Pop-Geste, nachdem ich einmal aufgetaucht bin.Ich habe gerade dieses Problem erlebt. Lassen Sie mich Ihnen meinen Code zeigen:
Der Fehler tritt aufgrund dieser Zeile auf:
Sie können sich nicht zur Unteransicht hinzufügen. Ich habe die Codezeile geändert in:
Der Fehler verschwand und ich konnte beide Ansichten sehen. Ich dachte nur, das würde jedem helfen, der ein Beispiel sehen möchte.
quelle
Suchen Sie Ihren Code nach "addSubview".
An einer der Stellen, an denen Sie diese Methode aufgerufen haben, haben Sie versucht, mit dieser Methode eine Ansicht zu ihrem eigenen Array für Unteransichten hinzuzufügen.
Beispielsweise:
Oder:
quelle
[View2.view addSubview:View2.view]
haben sich selbst als Unteransicht hinzugefügt.Ich denke, dass das Push / Popping von View-Controllern mit Animation zu jedem Zeitpunkt vollkommen in Ordnung sein sollte und das SDK die Warteschlange der Anrufe für uns freundlich behandeln sollte.
Daher ist dies nicht der Fall, und alle Lösungen versuchen, nachfolgende Pushs zu ignorieren, was als Fehler angesehen werden kann, da der endgültige Navigationsstapel nicht dem Code entspricht.
Ich habe stattdessen eine Push-Call-Warteschlange implementiert:
Es behandelt keine gemischten Warteschlangen von Push und Pops, aber es ist ein guter Anfang, um die meisten unserer Abstürze zu beheben.
Inhalt: https://gist.github.com/rivera-ernesto/0bc628be1e24ff5704ae
quelle
Tut mir leid, dass ich zu spät zur Party komme. Ich hatte kürzlich dieses Problem, bei dem meine Navigationsleiste beschädigt wurde, weil mehr als ein Ansichts-Controller gleichzeitig gedrückt wurde. Dies liegt daran, dass der andere Ansichts-Controller gedrückt wird, während der erste Ansichts-Controller noch animiert. Ausgehend von der nicht-formelhaften Antwort habe ich meine einfache Lösung gefunden, die in meinem Fall funktioniert. Sie müssen nur
UINavigationController
die pushViewController-Methode unterordnen und überschreiben und prüfen, ob die vorherige View Controller-Animation noch abgeschlossen ist. Sie können den Abschluss der Animation anhören, indem Sie Ihre Klasse zu einem Delegierten machenUINavigationControllerDelegate
und den Delegierten auf festlegenself
.Ich habe hier einen Kern hochgeladen , um die Dinge zu .
Stellen Sie einfach sicher, dass Sie diese neue Klasse als NavigationController in Ihrem Storyboard festlegen.
quelle
Basierend auf dem großartigen Hinweis von @RobP habe ich die Unterklasse UINavigationController erstellt , um solche Probleme zu vermeiden. Es handhabt das Schieben und / oder Knallen und Sie können sicher ausführen:
Wenn das Flag 'acceptConflictingCommands' auf true gesetzt ist (standardmäßig), wird dem Benutzer das animierte Pushing von vc1, vc2, vc3 und anschließend das animierte Poppen von vc3 angezeigt. Wenn 'acceptConflictingCommands' falsch ist, werden alle Push / Pop-Anforderungen verworfen, bis vc1 vollständig gepusht ist - daher werden andere 3 Aufrufe verworfen.
quelle
animated:true
flag ausführen ?Die Lösung von nonamelive ist fantastisch. Wenn Sie die private API jedoch nicht verwenden möchten, können Sie einfach die
UINavigationControllerDelegate
Methode ausführen. Oder Sie können die AnimationYES
in ändernNO
. Hier ist ein Beispiel für Code, den Sie erben können. Hoffe es ist hilfreich :)https://github.com/antrix1989/ANNavigationController
quelle
Ich hatte dieses Problem viel gesucht, es drückte möglicherweise zwei oder mehr VC gleichzeitig, was das Problem der Push-Animation verursacht. Sie können sich darauf beziehen: Selbst kann nicht als Unteransicht hinzugefügt werden 崩溃 解决 办法
Stellen Sie einfach sicher, dass gleichzeitig ein VC über den Übergangsfortschritt verfügt. Viel Glück.
quelle
Manchmal haben Sie fälschlicherweise versucht, eine Ansicht zu einer eigenen Ansicht hinzuzufügen.
Ändern Sie dies in Ihre Unteransicht.
quelle
Ich bin auch auf dieses Problem gestoßen. Bei der Analyse des Firebase-Protokolls stellte ich fest, dass dieses Problem nur beim Kaltstart der App auftritt. Also habe ich eine Demo geschrieben , die diesen Absturz reproduzieren kann.
.
Ich habe auch festgestellt, dass das Ausführen mehrerer Pushs nicht wieder dasselbe Problem verursacht, wenn der Root-Viewcontroller des Fensters angezeigt wird. (Sie können testColdStartUp (rootNav) in AppDelegate.swift kommentieren und den Kommentar testColdStartUp () in ViewController.swift auskommentieren.)
ps: Ich habe die Szene dieses Absturzes in meiner App analysiert. Wenn der Benutzer auf die Push-Benachrichtigung klickt, um die App kalt zu starten, befindet sich die App immer noch auf der Startseite und klickt auf einen weiteren Push, um zu springen. Zu diesem Zeitpunkt wird in der App möglicherweise der Absturz angezeigt. Meine aktuelle Lösung besteht darin, den Push- oder Universal Link-Kaltstart zwischenzuspeichern, um die App-Jump-Seite zu öffnen, auf die Anzeige des Rootview-Controllers zu warten und dann die Ausführung zu verzögern.
quelle
Versuchen Sie Ihre Navigation mit der Verzögerungsmethode, um die letzte Navigationsanimation zu vervollständigen.
[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>]
quelle
Eine Ansicht kann nicht selbst als Unteransicht hinzugefügt werden.
Die Ansichten behalten eine Eltern-Kind-Hierarchie bei. Wenn Sie also eine Ansicht als Unteransicht an sich hinzufügen, wird dies durch eine Ausnahme geschehen.
Wenn eine Klasse UIViewController ist, verwenden Sie self.view, um ihre Ansicht zu erhalten.
Wenn eine Klasse eine UIView-Klasse ist, verwenden Sie self, um ihre Ansicht zu erhalten.
quelle
Sie können sich nicht als Unteransicht hinzufügen, wenn es sich um eine UiViewController-Klasse handelt. Sie können sich selbst als Unteransicht hinzufügen, wenn es sich um eine UiView-Klasse handelt.
quelle
Wenn Sie einer Ansicht eine Unteransicht hinzufügen möchten, können Sie dies folgendermaßen tun.
quelle