Scrollen wird "hängen", wenn verschachtelte Bildlaufansichten verwendet werden

8

Problembeschreibung:

Ich habe ein iOS-Projekt zum Durchsuchen von Bildern mit verschachteltem UIScrollViews , das von berühmten Apples FotoScroller . Das Problem ist, dass manchmal Scrollen nur "hängt", wenn das Bild in der Breite oder Höhe gezoomt wird. Hier sehen Sie ein Beispiel, wie es in iPhone 4s für das Bild der Größe 935x1400 in der Höhe vergrößert angezeigt wird:

(Ich fange an, nach links zu ziehen, blättern aber sofort und verwirft diese Aktion und das Bild wird "hängen")

Abhilfe:

Ich habe eine Art Workaround gefunden, indem ich die Inhaltsgröße der inneren Bildlaufansicht nach dem Zoomen auf die nächste ganze Zahl eingestellt habe:

%Vor%

Aber diese Lösung ist nicht perfekt - einige Bilder werden jetzt mit ein Pixel breiten Streifen an den Seiten gezeigt. Bei iPhone 6 für Bild mit der Größe 690x14300 wird dies beispielsweise unten angezeigt:

Ich kann dieses Problem auch seltsamerweise auf iOS 7.0 - 10.1 reproduzieren, aber bei iOS 10.2 und größer funktioniert alles korrekt.

Frage:

Also, was mache ich falsch? Kann meine Reparatur verbessert werden?

Testprojekt:

Ich habe ein einfaches Testprojekt erstellt, um das beschriebene Problem zu veranschaulichen - NestedScrollingProblems . Bitte beachten Sie, dass sich meine Version von ImageScrollView leicht von der von Apple unterscheidet, weil ich andere Regeln für das Zoomen angewendet habe. Außerdem ist Workaround standardmäßig auskommentiert. (Projektcode ist ein bisschen chaotisch, sorry darüber)

    
Anton Malmygin 21.05.2017, 00:49
quelle

1 Antwort

0

Ich kann die Beiträge nicht kommentieren (noch nicht genug Wiederholungen).

Aber nach dem Aussehen (Apple's Docs) dieses Projekt deinits Bilder auf Bildlauf, dann re-inits sie, wenn sie geladen werden (siehe Zeile 350 in UIScrollView.m ). Und außerdem habe ich einen Kommentar in ImageScrollView.m (Zeile 346) bemerkt, der explizit besagt, dass diese Klasse das Caching vermeiden soll. Dies ist ein praktischer Weg für eine Demo, aber nicht für die Produktion, oder für eine reale Anwendung, bei der die Ladegeschwindigkeit im Vordergrund steht, was Sie wollen.

Ich habe auch bemerkt, dass Ihre App viel weiter scrollen muss, um die Seitennummerierung zu aktivieren. Dies ist entweder ein Fehler im Code oder es kann die Verzögerung selbst sein, die den Hauptthread daran hindert, die Seitennumerierung flüssig auszuführen. Oder wenn Sie eine so große Schwelle für die Paginierung haben wollten, würde ich empfehlen, sie für eine bessere Benutzererfahrung zu reduzieren, da moderne Smartphones Bildschirme viel breiter als die des iPhone 4S haben.

Um dies zu beheben,

Ich fand das Post (unten) auf SO, das zu haben scheint eine ziemlich anständige obj-c-Methode zum Zwischenspeichern und Abrufen von Bilddaten aus einem solchen Cache-Post-App-Start. Sie sollten in der Lage sein, es in Post-Launch-Methoden auch ziemlich einfach zu bearbeiten, oder es sogar mit dem Netzwerk verwenden, um Bilder aus dem Internet herunterzuladen. Sie müssen lediglich sicherstellen, dass Ihre UIImage-Ansichten ordnungsgemäß mit den von Ihnen verwendeten URL-Zeichenfolgen verknüpft sind, entweder durch eine Reihe von benutzerdefinierten Zeichenfolgenvariablen für jede Bildansicht oder durch Unterklassenbildung von UImageView in eine benutzerdefinierte Klasse und durch Hinzufügen der Cache-Methode damit Ihr Code einfacher aussieht. Hier ist die Methode und NSCahe Klasse aus diesem Beitrag von iOSfleer

NSCache-Klasse:

%Vor%

Und um nicht zu viel von dem zu ändern, was Sie gemacht haben, scheint es, dass sich die Methode displayImageWithInfo innerhalb von ImageScrollview.m auf die nächste (mit der Caching-Methode) zu verbessern scheint Anfangsladung. Ich würde auch einen Schritt weiter gehen, wenn ich Sie wäre, und eine Methode im Loop-Stil in der viewDidLoad -Methode des Controllers implementieren, um diese Bilder sofort zu speichern, damit sie beim Start schneller geladen werden können. Aber das liegt an dir.

%Vor%

Ich würde auch empfehlen, dies zu umgehen, ohne die Ansichten aus ihrem Superview auf scroll zu entfernen. Das Hinzufügen von Ansichten ist eine sehr schwere Aufgabe. Und gekoppelt mit Image Loading, kann für eine kleine CPU wie die auf Smartphones horrend schwer sein (da sie GPUs noch nicht haben ..). Um das zu betonen, erwähnt Apple sogar, dass es UIImages nicht wiedergibt, sobald sie angezeigt werden, die Formulierung ist subtil hier , aber es wird nicht explizit erwähnt, dass das Entfernen von Ansichten nach dem einmaligen Anzeigen (wie es in diesem Fall der Fall ist) optimiert wird. Ich denke, der beabsichtigte Gebrauch hier ist, das ImageView anzuzeigen, und einfach sein image Element später zu ändern, nachdem der Kontroller angezeigt wird.

  

Obwohl Bildobjekte alle plattformeigenen Bildformate unterstützen, ist es möglich   Es wird empfohlen, dass Sie PNG - oder JPEG - Dateien für die meisten Bilder in Ihrem verwenden   App Bildobjekte sind zum Lesen und Anzeigen beider Objekte optimiert   Formate, und diese Formate bieten eine bessere Leistung als die meisten anderen   Bildformate.

Das ist der Grund, warum Ansichten normalerweise in ihrer Super-Ansicht vor allen sichtbaren Lade-Methoden wie viewWillAppear und viewDidAppear hinzugefügt / initialisiert werden, oder wenn sie nach dem erstmaligen Laden erledigt werden, werden sie nur selten de-initialisiert, ihr Inhalt wird oft nur geändert und selbst dann wird es normalerweise asynchron (beim Herunterladen aus dem Web) gemacht, oder es wird aus einem Cache gemacht, was auch automatisch mit einigen Initialisierern gemacht werden kann (Sie können dies zu dem hinzufügen, was ich empfehle):

  

Verwenden Sie die imageNamed: inBundle: compatibleWithTraitCollection: -Methode (oder   die imageNamed: -Methode), um ein Bild aus einem Bildasset zu erstellen oder   Bilddatei, die sich im Hauptpaket Ihrer App befindet (oder in einer anderen bekannten Version)   bündeln). Da diese Methoden die Bilddaten automatisch zwischenspeichern,   Sie werden besonders für Bilder empfohlen, die Sie häufig verwenden.

Bei einer persönlichen Anmerkung würde ich versuchen, den Ansatz von UICollectionViews zu wählen. Insbesondere haben sie Delegaten, die das Zwischenspeichern von Inhalten automatisch durchführen, wenn Ansichten aus dem Fenster rollen (was genau diese Demo ist). Sie können diesen Methoden auch benutzerdefinierten Code hinzufügen, um den Scrolling-Effekt auch für diese Ansichten besser zu steuern. Sie könnten anfangs etwas schwierig zu verstehen sein, aber ich kann bestätigen, dass das, was Sie hier erreichen wollen, mit einem Bruchteil des Codes, den diese Demo verwendet, repliziert werden kann. Ich nehme auch die Tatsache, dass diese Demo 2012 als Hinweis erstellt wurde. Es ist eine sehr alte Demo und UICollectionViews erschienen zum Zeitpunkt der letzten Aktualisierung dieser Demo.Also würde ich sagen, dass Apple seit jeher darauf abzielt, denn alle inhaltsorientierten UIView-Unterklassen haben sowieso irgendeine Art von Vererbung von UIScrollView  (UICollectionView, UITableView, UITextView usw.). Einen Blick wert! UICollectionViews .

    
murphguy 26.05.2017 20:11
quelle