Ich habe ein Problem und habe es unten beschrieben.
Ich verwende UIViewControllerContextTransitioning
für benutzerdefinierte Übergänge.
Ich habe 2 View Controller, First View Controller und Second View Controller.
Jetzt möchte ich den zweiten Ansichts-Controller mit einer Animation zum ersten Ansichts-Controller hinzufügen. Ich habe es erreicht, jetzt ist der zweite Ansichts-Controller transparent, so dass wir den ersten Ansichts-Controller unter dem zweiten Ansichts-Controller sehen können.
Aber ich kann den Controller für die erste Ansicht nicht sehen, und ich kann nur einen schwarzen Bildschirm unter dem Controller für die zweite Ansicht sehen.
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
self.transitionContext = transitionContext;
if(self.isPresenting){
[self executePresentationAnimation:transitionContext];
}
else{
[self executeDismissalAnimation:transitionContext];
}
}
-(void)executePresentationAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
UIView* inView = [transitionContext containerView];
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
CGRect offScreenFrame = inView.frame;
offScreenFrame.origin.y = inView.frame.size.height;
toViewController.view.frame = offScreenFrame;
toViewController.view.backgroundColor = [UIColor clearColor];
fromViewController.view.backgroundColor = [UIColor clearColor];
inView.backgroundColor = [UIColor clearColor];
[inView insertSubview:toViewController.view aboveSubview:fromViewController.view];
// [inView addSubview:toViewController.view];
CFTimeInterval duration = self.presentationDuration;
CFTimeInterval halfDuration = duration/2;
CATransform3D t1 = [self firstTransform];
CATransform3D t2 = [self secondTransformWithView:fromViewController.view];
[UIView animateKeyframesWithDuration:halfDuration delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.5f animations:^{
fromViewController.view.layer.transform = t1;
}];
[UIView addKeyframeWithRelativeStartTime:0.5f relativeDuration:0.5f animations:^{
fromViewController.view.layer.transform = t2;
}];
} completion:^(BOOL finished) {
}];
[UIView animateWithDuration:duration delay:(halfDuration - (0.3*halfDuration)) usingSpringWithDamping:0.7f initialSpringVelocity:6.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
toViewController.view.frame = inView.frame;
} completion:^(BOOL finished) {
[self.transitionContext completeTransition:YES];
}];
}
Beim [self.transitionContext completeTransition:YES];
Aufruf verschwindet plötzlich der erste Ansichts-Controller und unter dem zweiten Ansichts-Controller wird ein schwarzer Bildschirm angezeigt.
Hat jemand eine Idee? Vielen Dank.
quelle
modalPresentationStyle = UIModalPresentationFullScreen
. Sie erhalten natürlich immer noch Ihre benutzerdefinierte Übergangsanimation.Ich denke, die Gründe dafür sollten besser erklärt werden.
Die Ansicht verschwindet, weil Sie die Ansicht des präsentierenden Ansichts-Controllers aus ihrer ursprünglichen Position (Ansichtshierarchie) herausnehmen, sie in die von Ihrem Animator bereitgestellte containerView einfügen, sie aber nach Abschluss der Animation nie wieder zurückgeben. Damit wird die Ansicht des View Controllers mit seiner Superview (containerView) vollständig aus dem Fenster entfernt.
In iOS 7 hat das System die Ansichten der View Controller, die an der Präsentation beteiligt sind (Präsentieren und Präsentieren), immer an ihre ursprünglichen Stellen zurückgesetzt, nachdem der Übergang automatisch abgeschlossen wurde. Dies ist bei einigen Präsentationsstilen in iOS 8 nicht mehr der Fall.
Die Regel ist sehr einfach: Der Animator sollte die Ansicht des präsentierenden Ansichtscontrollers nur bearbeiten, wenn die Ansicht dieses Ansichtscontrollers bis zum Ende des Übergangs vollständig ausgeblendet (aus der Ansichtshierarchie entfernt) wird . Mit anderen Worten bedeutet dies, dass nach Abschluss der anfänglichen Präsentationsanimation nur die Ansicht des präsentierten Ansichtscontrollers sichtbar ist und nicht die Ansicht des präsentierenden Ansichtscontrollers. Wenn Sie beispielsweise die Deckkraft der Ansicht des dargestellten Ansichtscontrollers auf 50% setzen und UIModalPresentationFullScreen verwenden, wird die Ansicht des dargestellten Ansichtscontrollers unter dem dargestellten nicht angezeigt. Wenn Sie jedoch UIModalPresentationOverFullscreen verwenden, werden Sie dies tun (die
shouldRemovePresentersView
Methode von UIPresentationController ist dafür verantwortlich, dies anzugeben).Lassen Sie den Animator die Ansicht des Controllers für die präsentierende Ansicht jederzeit bearbeiten. Wenn die Ansicht des Controllers für die Präsentationsansicht nach Abschluss der Animation während des gesamten Präsentationslebenszyklus sichtbar bleibt, muss sie zunächst überhaupt nicht animiert werden - sie bleibt einfach dort, wo sie ist. Zweitens, wenn der Besitz für diesen Ansichtscontroller auf den Präsentationscontroller übertragen wird, weiß der Präsentationscontroller höchstwahrscheinlich nicht, wie die Ansicht dieses Ansichtscontrollers bei Bedarf zu gestalten ist, beispielsweise wenn sich die Ausrichtung ändert, aber der ursprüngliche Eigentümer des Präsentationsansichtscontrollers tut dies .
In iOS 8 wurde die
viewForKey:
Methode eingeführt, um Ansichten abzurufen, die der Animator bearbeitet. Erstens ist es hilfreich, die oben beschriebene Regel zu befolgen, indem Sie nil zurückgeben, wenn der Animator die Ansicht nicht berühren sollte. Zweitens wird möglicherweise eine andere Ansicht zurückgegeben, die der Animator animieren kann. Stellen Sie sich vor, Sie implementieren eine Präsentation ähnlich dem Formularblatt. In diesem Fall möchten Sie der Ansicht des dargestellten Ansichts-Controllers Schatten oder Dekoration hinzufügen. Der Animator animiert stattdessen diese Dekoration und die Ansicht des dargestellten Ansichts-Controllers ist ein Kind der Dekoration.viewControllerForKey:
geht nicht weg, kann trotzdem verwendet werden, wenn ein direkter Zugriff auf Ansichts-Controller erforderlich ist, der Animator jedoch keine Annahmen über die Ansichten treffen sollte, die zum Animieren benötigt werden.Es gibt verschiedene Möglichkeiten, um ein Problem mit der Ansicht eines verschwindenden darstellenden Ansichtscontrollers zu beheben, wenn Sie sie explizit in die Containeransicht des Animators einfügen:
Wenn Sie die Ansicht des präsentierenden Ansichtscontrollers nicht animieren müssen, verwenden Sie diese Option
viewForKey:
, um Ansichten zum Animieren zu bringen, anstatt direkt die Ansichten des Controllers anzuzeigen.viewForKey:
kann keine oder sogar völlig andere Ansichten zurückgeben.Wenn Sie die Ansicht der Controller der präsentierenden Ansicht animieren möchten, sollten Sie die Verwendung des
UIModalPresentationFullScreen
Stils in Betracht ziehen oder weiterhinUIModalPresentationCustom
Ihre eigene Unterklasse von UIPresentationController verwenden und implementieren, wenn SieshouldRemovePresentersView
zurückkehrenYES
. Tatsächlich ist die Implementierung dieser Methode der Hauptunterschied zwischen internen PräsentationscontrollernUIModalPresentationFullScreen
undUIModalPresentationCustom
Stilen, abgesehen von der Tatsache, dass Sie mit letzteren benutzerdefinierte Präsentationscontroller verwenden können.In allen anderen seltenen Fällen müssen Sie die Ansicht des Controllers für die präsentierende Ansicht an den ursprünglichen Speicherort zurücksetzen, wie in anderen Antworten vorgeschlagen.
quelle
viewControllerForKey:
s basiert,view
wennviewForKey:
nil zurückgegeben wird, und ich ihn trotzdem manuell zum Fenster hinzufügen musste. Haben Sie ein Beispiel für Code, der ohne diese Problemumgehung funktioniert?viewForKey:
null zurückgegeben wird, müssen Sie die Ansicht des präsentierenden Ansichts-Controllers mit Sicherheit erneut zum Fenster hinzufügen, wenn Sie sie in Ihrem Animator daraus entfernen. Wenn viewForKey die Ansicht des tatsächlichen Ansichtscontrollers zurückgibt, kann diese Ansicht sicher verschoben werden, da UIKit sie nach Ablauf des Präsentationslebenszyklus wieder an ihre ursprüngliche Position verschieben würde.In iOS 8 müssen Sie die von zurückgegebenen Ansichten
viewForKey:
anstelle der.view
Eigenschaft der von zurückgegebenen Ansichtscontroller bearbeitenviewControllerForKey:
. Dies geht aus der Beta-Dokumentation nicht besonders hervor. Wenn Sie sich jedoch die Quelle für UIViewControllerTransitioning.h ansehen, sehen Sie diesen Kommentar obenviewControllerForKey:
:toViewController.view
Verwenden Sie also den Rückgabewert von , anstatt Frames usw. von anzupassen[transitionContext viewForKey:UITransitionContextToViewKey]
.Wenn Ihre App iOS7 und / oder Xcode 5 unterstützen muss, können Sie in UIViewController eine einfache Kategoriemethode wie die folgende verwenden:
Dann holen Sie sich Ihre
toViewController
undfromViewController
wie gewohnt, aber holen Sie sich die Ansichten mit[toViewController viewForTransitionContext:transitionContext]
.Bearbeiten: Es scheint einen Fehler zu geben, bei dem die Ansicht des Controllers für die Präsentationsansicht bei der Rückkehr von Null ist
viewForKey
, wodurch Sie keine modalen Übergänge vornehmen können, die die Präsentationsansicht überhaupt animieren (z. B. Abrutschen oder horizontales Umdrehen). Ich habe einen Fehler für iOS8 unter rdar: // 17961976 ( http://openradar.appspot.com/radar?id=5210815787433984 ) eingereicht . Siehe auch das Beispielprojekt unter http://github.com/bcherry/TransitionBugBearbeiten 2: Dank Graveley für den Vorschlag wird das Problem durch die Verwendung von UIModalPresentationFullScreen behoben. Vielleicht ist das kein Fehler. Apple beabsichtigt möglicherweise, dass UIModalPresentationCustom nur die Ansicht des eingehenden Modals ändert. Wenn Sie die ausgehende Ansicht ändern möchten, müssen Sie die Vollbilddarstellung der neuen Ansicht gewährleisten. In jedem Fall sollten Sie
viewForKey
UIModalPresentationFullScreen verwenden.quelle
manipulating
die Ansichten des VCs interpretiert werden sollte oder nicht ...viewForKey
Fehler auch im GM. Sind es auch andere? Haben Sie eine vernünftige Problemumgehung dafür gefunden?- viewForKey
// viewForKey: kann nil zurückgeben, was darauf hinweisen würde, dass der Animator die Ansicht des zugehörigen View Controllers nicht manipulieren sollte. Zurücknil
ist kein Fehler.viewForKey
die Ansicht von und die Ansicht von zurück. Vielleicht ist es beabsichtigt, dass für UIModalPresentationCustom Null zurückgegeben wird. Ich aktualisiere meinen Fehlerbericht und werde ihn hier veröffentlichen, wenn ich von Apple etwas darüber höre.modalPresentationStyle
Wenn ich nicht auf UIModalPresentationCustom eingestellt habe, wurde das Problem für mich behoben.Mit anderen Worten: Wenn Sie die Standardeinstellung von UIModalPresentationFullScreen beibehalten, anstatt UIModalPresentationCustom anzugeben, wurde das Problem mit der verschwindenden Ansicht behoben. Beachten Sie, dass das UIViewControllerTransitioningDelegate-Protokoll auch dann noch eingehalten wird, wenn es auf der Standardeinstellung belassen wird. Wenn ich mich richtig erinnere, war UIModalPresentationCustom einmal eine Anforderung.
Funktioniert bisher, habe dies nur für nicht interaktive Animationen versucht.
quelle
viewForKey:
anstelle.view
derviewControllerForKey:
Korrekturen behebt alle Probleme für mich.Ich habe diese äußerst nützliche Antwort in einem verwandten Thread von Lefteris gefunden: https://stackoverflow.com/a/27165723/3709173
Etwas zusammenfassen:
+1 in Ihrem benutzerdefinierten Übergang, fügen Sie toView nicht hinzu, wenn die Entlassungsanimation ausgeführt wird.
Hier demonstriert:
https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl=0 ohne Hacks! Es ist wie Magie! :) :)
quelle
In iOS 8 müssen Sie einen UIPresentationController erstellen und die folgende Methode im UIViewControllerTransitioningDelegate implementieren.
Weitere Informationen finden Sie im WWDC 2014-Video:
https://developer.apple.com/videos/wwdc/2014/?include=228
Es gibt auch einen Beispielcode aus dem WWDC mit dem Namen "LookInside: Presentation Controllers Adaptivity and Custom Animator Objects", den Sie von der WWDC 2014-Beispielcodepage herunterladen können.
Möglicherweise müssen Sie den Beispielcode ein wenig ändern. Die UIPresentationController-Init-Methode wurde geändert in:
Bevor es präsentiert und dann präsentiert wurde. Tauschen Sie sie einfach aus und es sollte funktionieren.
quelle
anstelle von [inView insertSubview: toViewController.view obenSubview: fromViewController.view]; füge einfach hinzu: [inView addSubview: toViewController.view];
Hier sehen Sie ein Beispiel: link und es funktioniert unter iOS 7 und iOS 8
quelle
Hier ist eine Objective C-Version von Ashs Fix.
Ich musste die Reihenfolge austauschen und die Methode [TransitionContext completeTransition:] aufrufen, nachdem ich die Ansicht wieder hinzugefügt hatte, um einen neuen Ansichts-Controller aus dem Block zum Schließen der Entlassung eines anderen Ansichts-Controllers zu präsentieren, damit er richtig funktioniert.
Ich weiß nicht, dass dies das Problem für alle beheben wird, aber es funktioniert in meiner App. Prost!
quelle
Ich fand, dass dies für Obj-C gut funktioniert hat:
Scheint sowohl auf ios7 als auch auf ios8 gut zu funktionieren.
quelle
Ich habe festgestellt, dass
viewForKey:UITransitionContextToViewKey
auf ios8 null zurückgegeben wird. Wenn es also Null ist, greife ich auf die Ansicht vom 'to'-View-Controller zu.Dies scheint jedoch dazu zu führen, dass die 'to'-Ansicht beim
completeTransition:YES
Aufruf nicht vom Container in das Fenster verschoben wird. Wenn alsoviewForKey:UITransitionContextToViewKey
null zurückgegeben wird, falle ich zu nulltoVC.view
und verfolge die Tatsache, dass es null zurückgegeben hat. Nach Abschluss verschiebe ich es in die anfängliche Übersicht des Containers (die zufällig das Fenster ist).Dieser Code funktioniert also sowohl unter iOS7 als auch unter iOS8 und sollte auch unter iOS9 funktionieren, selbst wenn sie ihn beheben oder nicht.
quelle
Ich habe festgestellt, dass dieser Fehler (und viele mehr!) Verschwindet, wenn Sie ihn einstellen
modalPresentationStyle = UIModalPresentationFullScreen
. Sie erhalten natürlich immer noch Ihre benutzerdefinierte Übergangsanimation.quelle
Ich habe mich auch mit diesem Thema beschäftigt. Ich wollte einen benutzerdefinierten Übergang mit einem halbtransparenten Hintergrund erstellen, in dem ich immer noch den Ansichts-Controller sehen konnte, von dem ich kam, aber nur einen schwarzen Hintergrund. Ich fand, dass Mark Arons Antwort in diesem Thread mir geholfen hat, aber sie ist in Ziel C geschrieben. Hier ist eine Swift 3-Version dieser Antwort, die ich für iOS 9 und iOS 10 getestet habe:
Erstellen Sie eine Unterklasse von UIPresentationController. Überschreiben Sie die shouldRemovePresentersView wie folgt auf false:
Geben Sie an der Stelle, an der Sie den neuen Ansichtscontroller instanziieren und seinen Übergangsdelegierten festlegen, an, dass er einen benutzerdefinierten modalen Präsentationsstil wie folgt anzeigen soll:
Überschreiben Sie nun die PresentationController-Methode Ihres UIViewControllerTransitioningDelegate und geben Sie Ihren benutzerdefinierten UIPresentationController zurück. Ich hatte meine als Erweiterung meiner aktuellen Klasse:
Eine andere Sache, die Sie beachten sollten, ist, dass Sie nicht versuchen sollten, Ihre fromView in Ihrer presentAnimator-Klasse zu referenzieren. Dies ist Null und Sie erhalten zur Laufzeit einen Fehler. Anders als das, wenn Sie Dinge wie Dinge implementieren, erhalten Sie Ihren benutzerdefinierten Übergang mit seiner Animation und einem halbtransparenten Hintergrund, wenn Sie einen erstellen.
quelle
presentationController(forPresented presented UIViewController,...
hängen, bis ich ein Beispiel fand, das die neue Swift 3-API zeigte, weil die vorherige Swift-API den Complier nicht verärgerte, aber nicht aufgerufen wurde.Nachdem ich auf dieses Problem gestoßen war, war ich sehr verwirrt, weil ich vor nicht allzu langer Zeit etwas fast Identisches geschrieben hatte, das gut funktionierte. Kam hierher und suchte nach Antworten, um Korrekturen zu finden, die ziemlich hackig aussehen und die Grundursache nicht zu verstehen scheinen ... es ist eigentlich sehr einfach zu beheben.
Einige Antworten erwähnen den Wechsel
modalPresentationStyle
zu.overFullScreen
. Das ist richtig,.overCurrentContext
würde auch funktionieren. Dies wird erwartet und das Verhalten von Apple dokumentiert. Aber warum funktioniert das nicht für alle? Warum all der hackige Code und Kombinationen davon mit etwas anderem und verrückten Sachen, die du nicht machen solltest?Es stellt sich heraus, dass Sie den Präsentationsstil VOR DEN VIEW-LADUNGEN festlegen müssen . Nicht danach. Führen Sie dies in init oder vom vorherigen Controller aus oder wie Sie möchten - solange die Ansicht geladen wird.
quelle
.overCurrentContext
vor dem Laden der Ansicht (iminit
Ansichts-Controller) eingestellt und das Problem tritt immer noch aufDie Verwendung des neuen UIModalPresentationOverCurrentContext hat dies für mich behoben. Mein ursprünglicher Übergang unter iOS 7 bestand darin, einen unscharfen Hintergrund der Ansicht unter dem Modal zu haben.
quelle
Ok, Leute, ich denke, ich löse einen Fall, in dem 'ein funktionierender Animator' nicht mehr richtig funktioniert, wenn Sie eine App in iOS 13 und höher erstellen.
Env Xcode 11.1, iOS 13.1
Problem
Was ich tun möchte, ist sehr einfach: Ich habe eine Sammlungsansicht. Wenn auf eine Zelle getippt wird, wechselt sie zu einer Detailansicht. Anstatt den langweiligen Standardstil "Modal präsentieren" zu verwenden, möchte ich ihn interessanter gestalten. Deshalb habe ich einen Animator für den Übergang zum View Controller geschrieben.
Ich habe den Übergang in IB per Drag & Drop von meiner Sammlungs-VC zur Detail-VC eingerichtet. Der Stil des Segues ist "Modal präsentieren" und die Präsentation ist auf "Vollbild" eingestellt.
Wenn die Detailansicht angezeigt wird, funktioniert alles wie erwartet. Wenn ich jedoch die Detailansicht verwerfe und zur Sammlungsansicht zurückkehre, kann ich nur die animierte Detailansicht sehen. Die Sammlungsansicht ist einfach verschwunden. Ich stocherte hier und da und habe ein paar Entdeckungen
1. Gleich nachdem die folgende Zeile von der Funktion 'animateTransition ()' aufgerufen wurde, wird die Sammlungsansicht fortgesetzt und angezeigt
2. Solange die Detailansicht die Sammlungsansicht nicht vollständig abdeckt, verschwindet die Sammlungsansicht nicht, wenn sie von der Detailansicht zurückkehrt
Lösung
Um ehrlich zu sein, weiß ich wenig darüber, wie der animierte Übergang funktioniert. Ich kann also nur diesem und dem anderen Beitrag folgen und jede der Antworten ausprobieren. Leider funktioniert keiner von ihnen für mich. Schließlich kam ich zu einem Punkt, an dem ich nur noch den Präsentationsstil von Segue in IB optimieren kann (was ich ganz am Anfang hätte tun sollen). Wenn ich die Präsentation auf "Über Vollbild" setze, geschieht ein Wunder und mein Problem ist gelöst. Die Detailansicht kann im Vollbildmodus mit Animation angezeigt werden. Wenn sie geschlossen wird, kann ich sowohl die Sammlungsansicht als Hintergrundansicht als auch die animierte Detailansicht anzeigen.
Dann noch eine Entdeckung entlang der Straße
3.Um auf 'toView' und 'fromView' zu verweisen, funktionieren beide folgenden Methoden
Indirekt:
Direkt Weg:
Aber als ich den Segue-Stil auf "Over Full Screen" umgestellt habe, gibt der direkte Weg "nil" sowohl für "toView" als auch für "fromView" zurück und funktioniert nur indirekt. Dieses Problem wird auch in einem anderen Beitrag erwähnt , daher denke ich, dass es sich lohnt um meine kleine Entdeckung hier zu posten.
Hoffe, dass dies in Zukunft für jemanden hilfreich sein wird.
quelle
Ich hatte das gleiche Problem beim Entlassen eines Inhaltsansichts-Controllers.
In meiner App zeigt dieser übergeordnete Ansichts-Controller einen untergeordneten Ansichts-Controller (der vc darstellt) modal an. Wenn dann auf eine Unteransicht in der untergeordneten VC getippt wird, wird eine andere VC angezeigt (die ich als Inhaltsansichts-Controller bezeichne (präsentierte VC)).
Mein Problem ist, dass beim Verwerfen der contentVC (jetzt der präsentierenden VC) die untergeordnete VC (jetzt die präsentierte VC) angezeigt wird. Sobald mein benutzerdefinierter Übergang abgeschlossen ist, verschwindet die untergeordnete VC plötzlich und zeigt die übergeordnete VC an.
Was ich getan habe, um dieses Problem zu lösen, ist zu
.modalPresentationStyle
von parentVC präsentierte childVC von der Standardeinstellung.automatic
in.fullscreen
..modalPresentationStyle
von contentVC auf.fullscreen
.Dies löst das Problem. Ihr Kind VC wird jedoch nicht als Kartenblatt über parentVC angezeigt (bei Verwendung)
.overCurrentContext
oder automatisch) das in iOS 13 neu ist.Würde gerne wissen, ob es eine Lösung gibt, die das Kartenformat für das childVC beibehält, wenn es vom Elternteil präsentiert wird.
quelle
Fügt einen View Controller als untergeordnetes Element eines anderen View Controllers hinzu.
Überprüfen Sie und lassen Sie es mich wissen.
quelle