
Der 
Drag & Drop Mechanismus unter 
iOS 11 und 
iOS 12 ist eine Möglichkeit, Daten sowohl innerhalb einer einzelnen Anwendung als auch zwischen verschiedenen Anwendungen grafisch asynchron zu kopieren oder zu verschieben. Obwohl diese Technologie etwa 30 Jahre alt ist, hat sie sich unter 
iOS buchstäblich zu einem „Durchbruch“ entwickelt, da Sie mit 
multitouch beim Ziehen auf 
iOS frei mit dem Rest des Systems interagieren und Daten zum Zurücksetzen aus verschiedenen Anwendungen sammeln können.
iOS können mehrere Elemente gleichzeitig erfasst werden. Darüber hinaus müssen sie für die Auswahl nicht bequem zugänglich sein: Sie können das erste Objekt nehmen, dann zu einer anderen Anwendung gehen und etwas anderes greifen - alle Objekte werden auf einem „Stapel“ unter Ihrem Finger gesammelt. Rufen Sie dann das Universal Dock auf dem Bildschirm auf, öffnen Sie dort eine beliebige Anwendung und erfassen Sie das dritte Objekt. Wechseln Sie dann mit den ausgeführten Anwendungen zum Bildschirm und speichern Sie sie, ohne die Objekte freizugeben, in einem der geöffneten Programme. Eine solche Handlungsfreiheit ist auf dem 
iPad , auf dem 
iPhone ist die 
Drag & Drop Abdeckung in 
iOS auf das Framework einer Anwendung beschränkt.
Die beliebtesten Anwendungen ( 
Safary , 
Chrome , 
IbisPaint X , 
Mail , 
Photos , 
Files usw.) verfügen bereits über einen 
Drag & Drop Mechanismus. Darüber hinaus stellte 
Apple den Entwicklern eine sehr einfache und intuitive 
API zum Einbetten des 
Drag & Drop Mechanismus in Ihre Anwendung zur Verfügung. Der 
Drag & Drop Mechanismus funktioniert genau wie Gesten in 
UIView und verwendet das Konzept der 
Interaktionen , ähnlich wie Gesten. Sie können sich den 
Drag & Drop Mechanismus also einfach als eine wirklich leistungsstarke Geste vorstellen.
Es ist ebenso wie Gesten sehr einfach in Ihre Anwendung zu integrieren. Insbesondere, wenn Ihre Anwendung die 
UITableView- Tabelle oder die 
UICollectionView- Auflistung verwendet, da für sie 
API Drag & Drop verbessert und auf eine höhere Abstraktionsebene angehoben wird, da die 
Collection View Auflistung selbst Ihnen beim 
indexPath des Auflistungselements hilft, das Sie ziehen und 
ablegen möchten 
Drag . Sie weiß, wo sich Ihr Finger befindet, und interpretiert ihn als den 
Indexpfad des Sammlungselements, das Sie gerade ziehen. Ziehen Sie ihn als den 
Indexpfad des Sammlungselements, in dem Sie etwas 
ablegen . Die 
Collection View Auflistung liefert Ihnen also 
indexPath , ansonsten ist es absolut dieselbe 
API Drag & Drop wie für eine normale 
UIView .
Der 
Drag & Drop Prozess unter 
iOS besteht aus 4 verschiedenen Phasen:
Heben Sie an
Heben (Heben) - Dies ist der Fall, wenn der Benutzer eine 
lange Druckgeste ausführt, die das Element angibt, das "Drag & Drop" sein soll. In diesem Moment wird eine sehr leichte sogenannte " 
lift preview " des angezeigten Elements gebildet, und dann beginnt der Benutzer, seine Finger zu ziehen.

Ziehen (Drag & Drop)
Ziehen (Drag & Drop) - Dies ist, wenn der Benutzer das Objekt auf der Oberfläche des Bildschirms verschiebt. Während dieser Phase kann die " 
lift preview " für dieses Objekt geändert werden (ein grünes "+" Pluszeichen oder ein anderes Zeichen wird angezeigt) ...

... eine gewisse Interaktion mit dem System ist ebenfalls zulässig: Sie können auf ein anderes Objekt klicken und es der aktuellen Drag & Drop-Sitzung hinzufügen:

Drop
Ein Tropfen tritt auf, wenn der Benutzer einen Finger hebt. In diesem Moment können zwei Dinge passieren: Entweder wird das 
Drag Objekt zerstört oder das 
Drop Objekt wird am Ziel „fallen gelassen“.

Datenübertragung
Wenn der Drag-and-Drop-Vorgang nicht abgebrochen wurde und das Zurücksetzen des 
Drop- Vorgangs stattgefunden hat, erfolgt die 
Datenübertragung (Datenübertragung), bei der der Drop-Point Daten von der Quelle anfordert, und die asynchrone Datenübertragung erfolgt.
In diesem Tutorial zeigen wir Ihnen, wie Sie 
den Drag & Drop Mechanismus mithilfe der Demo-Anwendung "Bildergalerie" 
aus Stanfords Hausaufgabenkurs CS193P einfach in Ihre 
iOS App 
integrieren können .
Wir werden der 
Collection View Möglichkeit geben, uns AUSSERHALB mit Bildern zu füllen und INSIDE-Elemente mithilfe des 
Drag & Drop Mechanismus neu zu organisieren. Darüber hinaus wird dieser Mechanismus verwendet, um unnötige Elemente der 
Collection View in einen "Papierkorb" zu 
werfen , der eine normale 
UIView darstellt und durch eine Schaltfläche im Navigationsbereich dargestellt wird. Wir können in unserer Galerie gesammelte Bilder auch mithilfe des 
Drag & Drop Mechanismus für andere Anwendungen 
Drag & Drop , z. B. 
Notes oder 
Notes oder 
Mail oder eine Fotobibliothek ( 
Photo ).
Bevor ich mich jedoch auf die Implementierung des 
Drag & Drop Mechanismus in der Demo-Anwendung „Image Gallery“ konzentriere, werde ich kurz auf die Hauptkomponenten eingehen.
Funktionen der Demo-Anwendung "Image Gallery"
Die Benutzeroberfläche der Image Gallery-Anwendung ist sehr einfach. Dies ist ein „Bildschirmausschnitt“ des in den 
Navigation Controller eingefügten 
Image Gallery Collection View Controller für die 
Image Gallery Collection View Controller :

Der zentrale Teil der Anwendung ist sicherlich der 
Image Gallery Collection View Controller , der von der 
ImageGalleryCollectionViewController- Klasse mit dem Image Gallery-Modell als Variable 
var imageGallery = ImageGallery () unterstützt wird :

Das Modell wird durch eine 
struct ImageGallery- Struktur dargestellt, die ein Array von 
Bildbildern enthält, wobei jedes Bild durch eine 
struct ImageModel- Struktur beschrieben wird, die die 
URL Bildspeicherort- 
URL (wir werden das Bild selbst nicht speichern) und ihr Seitenverhältnis enthält:

Unser 
ImageGalleryCollectionViewController implementiert das 
DataSource- Protokoll:

Die benutzerdefinierte Zelle in der 
Zellsammlung enthält ein 
imageView- Bild 
: UIImageView! und 
Spinner- Aktivitätsindikator 
: UIActivityIndicatorView! und wird von der benutzerdefinierten 
subclass ImageCollectionViewCell der UICollectionViewCell- Klasse unterstützt:

Public API der 
ImageCollectionViewCell- Klasse ist die 
imageURL- Bild- 
URL . Sobald wir es installieren, wird unsere 
UI aktualisiert, 
dh die Daten für das Image werden in dieser 
imageURL asynchron 
ausgewählt und in der Zelle angezeigt. Während Daten aus dem Netzwerk abgerufen werden, funktioniert die 
Spinner- Aktivitätsanzeige und zeigt an, dass wir gerade Daten abrufen.
Ich verwende die globale Warteschlange 
(qos: .userInitiated) mit dem Argument 
qos Quality of Service, um Daten unter einer bestimmten 
URL abzurufen , die auf 
.userInitiated festgelegt ist, da ich die Daten auf Anfrage des Benutzers auswähle:

Jedes Mal, wenn Sie Ihre eigenen Variablen innerhalb eines Abschlusses verwenden, in unserem Fall 
imageView und 
imageURL , zwingt Sie der Compiler, sich 
selbst vor sie zu stellen 
. so dass Sie sich fragen: "Gibt es eine" Speicher-zyklische Verbindung "?" Wir haben hier keinen expliziten „ 
memory cycle “, weil das 
Selbst selbst keinen Zeiger auf diesen Abschluss hat.
Beim Multithreading sollten Sie jedoch berücksichtigen, dass die 
Zellen in der 
Collection View dank der Methode 
dequeueReusableCell wiederverwendbar sind. Jedes Mal, wenn eine Zelle (neu oder wiederverwendet) auf dem Bildschirm angezeigt wird, wird das Bild asynchron aus dem Netzwerk heruntergeladen (zu diesem Zeitpunkt dreht sich der „ 
Spinner “ der 
Spinner- Aktivitätsanzeige).
Sobald der Download abgeschlossen ist und das Bild empfangen wurde, wird die 
UI dieser Sammelzelle aktualisiert. Wir warten jedoch nicht auf das Laden des Bildes, sondern scrollen weiter durch die Sammlung, und die von uns markierte Sammlungszelle verlässt den Bildschirm, ohne unsere 
UI zu aktualisieren. Unten sollte jedoch ein neues Bild angezeigt werden, und dieselbe Zelle, die den Bildschirm verlassen hat, wird wiederverwendet, jedoch für ein anderes Bild, das die 
UI schnell laden und aktualisieren kann. Zu diesem Zeitpunkt kehrt das zuvor in dieser Zelle gestartete Laden des Bildes zurück und der Bildschirm wird aktualisiert, was zu einem falschen Ergebnis führt. Dies liegt daran, dass wir verschiedene Dinge ausführen, die mit dem Netzwerk in verschiedenen Threads funktionieren. Sie kommen zu unterschiedlichen Zeiten zurück.
Wie können wir die Situation beheben?
Im Rahmen des von uns verwendeten 
GCD- Mechanismus können wir den Download des Bildes der Zelle, die den Bildschirm verlassen hat, nicht abbrechen. Wenn unsere 
imageData- Daten aus dem Netzwerk 
eingehen , können wir jedoch die 
URL URL überprüfen, die das Laden dieser Daten verursacht hat, und sie mit der 
URL vergleichen, die der Benutzer haben möchte diese Zelle im Moment, d. 
h . 
imageURL . Wenn sie nicht übereinstimmen, aktualisieren wir die 
UI Zelle nicht und warten auf die benötigten Bilddaten:

Diese scheinbar absurde Codezeile 
url == self.imageURL sorgt dafür, dass in einer Umgebung mit mehreren Threads, die eine nicht standardmäßige Vorstellungskraft erfordert, alles korrekt funktioniert. Tatsache ist, dass einige Dinge in der Multithread-Programmierung in einer anderen Reihenfolge ablaufen, als der Code geschrieben wurde.
Wenn die Bilddaten nicht ausgewählt werden konnten, wird ein Bild mit einer Fehlermeldung in Form der Zeichenfolge "Fehler" und einem Emoji mit "Stirnrunzeln" generiert. Nur der leere Bereich in unserer 
Collection View kann den Benutzer ein wenig verwirren:

Wir möchten nicht, dass das Bild mit der Fehlermeldung das 
Seitenverhältnis dieses 
Fehlerbilds wiederholt, da in diesem Fall der Text zusammen mit dem Emoji gestreckt oder komprimiert wird. Wir möchten, dass es neutral ist - quadratisch, das heißt, es hat ein Seitenverhältnis nahe 1,0.

Wir müssen unseren 
Controller über diesen Wunsch informieren, damit er das Seitenverhältnis von Seitenverhältnis für den entsprechenden 
Indexpfad in seinem 
imageGallery- Modell 
korrigiert . Dies ist eine interessante Aufgabe, es gibt viele Möglichkeiten, sie zu lösen, und wir werden die einfachste auswählen - mit 
optionalem Verschluss 
var closeAspectRatio: (() -> Void)? . Es kann gleich 
Null sein und muss nicht installiert werden, wenn dies nicht erforderlich ist:

Beim Aufruf der Closure 
changeAspectRatio? () Bei fehlerhaftem Datenabruf verwende ich die 
optionale Kette. Jetzt kann jeder, der an einer Art von Einstellungen interessiert ist, wenn er ein fehlerhaftes Bild empfängt, diesen Abschluss auf etwas Bestimmtes setzen. Und genau das tun wir in unserem 
Controller in der 
cellForItemAt- Methode:

Details finden Sie 
hier .
Um Bilder mit dem richtigen 
Aspektverhältnis anzuzeigen , wird die 
sizeForItemAt- Methode des 
UICollectionViewDelegateFlowLayout- Delegaten 
verwendet :

Zusätzlich zur 
Collection View haben wir auf unserer 
UI im Navigationsbereich eine 
Leistenschaltfläche mit einem benutzerdefinierten 
GarbageView- Bild platziert, das einen "Papierkorb" als 
Unteransicht enthält :

In dieser Abbildung werden die Hintergrundfarben für 
GarbageView selbst und die 
UIButton- Schaltfläche mit dem Bild der "Mülltonne" (tatsächlich gibt es einen transparenten Hintergrund) speziell geändert, sodass Sie sehen, dass der Benutzer, der die Bilder der Galerie in die "Mülltonne" "entleert". viel mehr Handlungsspielraum beim „Ablegen“ von 
Drop als nur das Mülleimersymbol.
Die 
GarbageView- Klasse 
verfügt über zwei Initialisierer und beide verwenden die 
setup () -Methode:

In der 
setup () -Methode füge ich außerdem 
myButton als 
Unteransicht mit dem Bild der "Mülltonne" hinzu, das aus dem Standard- 
Bar Button :

Ich habe einen transparenten Hintergrund für 
GarbageView festgelegt :

Die Größe der Mülltonne und ihre Position werden in der 
layoutSubviews () -Methode der 
UIView- Klasse abhängig von den 
Grenzen der angegebenen 
UIView bestimmt :

Dies ist die erste Version der Demo-Anwendung "Image Gallery". Sie befindet sich auf 
Github im Ordner " 
ImageGallery_beginning ". Wenn Sie diese Version der Anwendung "Bildergalerie" ausführen, sehen Sie das Ergebnis der Anwendung, die an Testdaten arbeitet, die wir anschließend löschen und die "Bildergalerie" ausschließlich AUSSEN ausfüllen:

Der Plan zur Implementierung des 
Drag & Drop Mechanismus in unserer Anwendung lautet wie folgt:
- Zunächst werden wir unserer Collection ViewMöglichkeit geben, Drag- from-UIImage- Bilder sowohl extern als auch lokal zu ziehen.
- Dann werden wir unserer Sammlung von Collection Viewbeibringen, "gezogenes"Dragextern oder lokal von UIImage zu akzeptieren.
- Wir werden auch unsere GarbageView mit der Mülltonne-Schaltfläche lehren, UIImage- Bilder zu akzeptieren, die aus der lokalen Collection Viewund sie aus derCollection Viewentfernen
Wenn Sie am Ende dieses Tutorials alle erforderlichen Codeänderungen vornehmen, erhalten Sie die endgültige Version der Demoanwendung „Image Gallery“, in der der 
Drag & Drop Mechanismus implementiert wurde. Es befindet sich auf 
Github im Ordner 
ImageGallery_finished .
Die Leistung des 
Drag & Drop Mechanismus in Ihrer 
Collection View von zwei neuen Delegierten bereitgestellt.
Die Methoden des 
ersten Delegaten, dragDelegate , sind so konfiguriert, dass die Drag & Drop- 
Drags initialisiert und angepasst werden.
Die Methoden des zweiten Delegaten, 
dropDelegate , vervollständigen das Ziehen und Ablegen von 
Drags und bieten im Grunde genommen Datenübertragungs- und benutzerdefinierte Animationseinstellungen, wenn 
Drop zurückgesetzt wird, sowie andere ähnliche Dinge.
Es ist wichtig zu beachten, dass beide Protokolle völlig unabhängig sind. Sie können das eine oder andere Protokoll verwenden, wenn Sie nur 
Drag oder nur Drop 
Drop müssen. Sie können jedoch beide Protokolle gleichzeitig verwenden und 
Drag & Drop gleichzeitig 
Drag & 
Drop , wodurch zusätzliche Funktionen eröffnet werden 
Drag & Drop Mechanismus zum Neuordnen von Elementen in Ihrer 
Collection View .
Drag & Drop Drag Elemente aus der Collection View
Das Implementieren des 
Drag Protokolls ist sehr einfach. Das erste, was Sie immer tun sollten, ist, sich 
selbst als 
DragDelegate- Delegat 
festzulegen :

Und ganz oben in der 
ImageGalleryCollectionViewController- Klasse 
sollten Sie 
natürlich "Ja" sagen. Wir implementieren das 
UICollectionViewDragDelegate- Protokoll:

Sobald wir dies tun, beginnt der Compiler sich zu beschweren, wir klicken auf den roten Kreis und werden gefragt: "Möchten Sie die erforderlichen Methoden des 
UICollectionViewDragDelegate- Protokolls 
hinzufügen ?"
Ich antworte: "Natürlich will ich!" und klicken Sie auf die Schaltfläche 
Fix :

Die einzige erforderliche Methode des 
UICollectionViewDragDelegate- Protokolls ist die 
itemsForBeginning- Methode, die dem 
Drag System 
mitteilt , dass wir sie ziehen und 
ablegen . Die Methode 
itemsForBeginning wird aufgerufen, wenn der Benutzer beginnt, eine Zelle in der Auflistungszelle zu "ziehen" (zu ziehen).
Beachten Sie, dass bei dieser Methode die 
Collection View Auflistung 
indexPath hinzugefügt 
hat . Dies sagt uns, welches Element der Sammlung, welchen 
Indexpfad wir ziehen und 
ablegen werden. Dies ist für uns sehr praktisch, da die Anwendung für die Verwendung der Argumente 
session und 
indexPath verantwortlich ist , um 
herauszufinden , wie mit diesem Drag & Drop von 
Drag umgegangen werden soll .
Wenn das Array 
[UIDragItems] der " 
ziehbaren " Elemente zurückgegeben wird, wird das "Ziehen" des 
Ziehens initialisiert. Wenn das leere Array 
[] zurückgegeben wird, wird das "Ziehen" des 
Drag ignoriert.
Ich werde eine kleine 
private DragItems-Funktion (at: indexPath) mit dem Argument 
indexPath erstellen . Es gibt das Array 
[UIDragItem] zurück, das wir 
benötigen .

Wie sieht ein Drag & Drop- 
UIDragItem aus ?
Er hat nur eine sehr wichtige Sache namens 
itemProvider . 
itemProvider ist nur etwas, das Daten bereitstellen kann, die gezogen werden.
Und Sie haben das Recht zu fragen: "Was ist mit dem" Ziehen und Ablegen "eines 
UIDragItem- Elements, das einfach keine Daten enthält?" Das Element, das Sie ziehen möchten, enthält möglicherweise keine Daten, da das Erstellen dieser Daten ein kostspieliger Vorgang ist. Dies kann ein Bild sein oder etwas, das das Herunterladen von Daten aus dem Internet erfordert. Das Tolle ist, dass der 
Drag & Drop Vorgang vollständig asynchron ist. Wenn Sie mit dem Ziehen und Ablegen beginnen, ist 
Drag wirklich ein sehr leichtes Objekt ( 
lift preview ). Sie ziehen es überall hin und während dieses "Ziehens" passiert nichts. Sobald Sie Ihr Objekt jedoch „ 
ablegen“ , muss es als 
itemProvider Ihr "gezogenes" und "geworfenes" Objekt wirklich mit realen Daten versorgen, selbst wenn dies eine gewisse Zeit in 
Anspruch nimmt.
Glücklicherweise gibt es viele integrierte 
itemProvider . Hierbei handelt es sich um Klassen, die bereits in 
iOS und 
itemPoviders sind , z. B. 
NSString , mit dem Sie Text ohne Schriftarten ziehen und 
NSString können. Dies ist natürlich ein 
UIImage- Bild. Sie können 
UIImages- Bilder 
überall auswählen und ziehen und 
ablegen . Die 
NSURL- Klasse, die absolut wunderbar ist. Sie können zur 
Web gehen, die 
URL auswählen und sie an einer beliebigen Stelle ablegen. Dies kann ein Link zu einem Artikel oder eine 
URL für ein Bild sein, wie es in unserer Demo sein wird. Dies sind die Farbklassen von 
UIColor , 
MKMapItem- Kartenelement, 
CNContact- Kontakt aus dem Adressbuch. Sie können viele Dinge auswählen und ziehen. Alle von ihnen sind 
itemProvider .
Wir werden das 
UIImage- Bild per Drag & Drop 
verschieben . Es befindet sich in der 
Zellenzelle der 
Collection View mit 
indexPath , wodurch ich die 
Zellenzelle auswählen, die 
Outlet Bildansicht daraus 
abrufen und das 
Bildbild abrufen kann .
Lassen Sie uns diese Idee mit ein paar Codezeilen ausdrücken.
Zuerst 
fordere ich meine 
Collection View zu einer 
Zelle für das Element an, das diesem 
Indexpfad entspricht .

Die 
cellForItem (at: IndexPath) -Methode für die 
Collection View funktioniert nur für sichtbare Zellen, aber in unserem Fall funktioniert sie natürlich, da ich das 
Drag Sammlungselement auf den Bildschirm 
ziehe und ablege und es sichtbar ist.
Also habe ich eine "ziehbare" Zellzelle.
Als nächstes benutze ich den 
als Operator 
? zu dieser Zelle, so dass es einen TYP meiner benutzerdefinierten 
subclass . Und wenn dies funktioniert, erhalte ich eine 
Outlet ImageView , aus der ich das Image- 
Image entnehme. Ich habe gerade das 
Bild für diesen 
indexPath "aufgenommen".
Nachdem ich nun ein 
Bildbild habe, muss ich nur noch eines dieser 
UIDragItems erstellen, indem 
ich das resultierende 
Bild als 
itemProvider verwende , 
dh das, was uns die Daten liefert.
Ich kann 
dragItem mit dem 
UIDragItem- Konstruktor erstellen, der 
itemProvider als Argument verwendet:

Anschließend erstellen wir einen 
itemProvider für das Bild 
, auch mit dem 
NSItemProvider- Konstruktor. Es gibt mehrere Konstruktoren für 
NSItemProvider , aber unter ihnen gibt es einen wirklich wunderbaren - 
NSItemProvider (Objekt: NSItemProviderWriting) :

Sie geben das Objektobjekt einfach 
an diesen 
NSItemProvider- Konstruktor weiter, und er weiß, wie 
itemProvider daraus erstellt wird. Als solches 
Objekt gebe ich dem Bild das Bild 
, das ich von der 
Zellenzelle erhalten 
habe, und erhalte 
itemProvider für 
UIImage .
Und das ist alles. Wir haben 
dragItem erstellt und sollten es als Array mit einem Element zurückgeben.
Aber bevor ich wieder dragItem , ich werde noch eine Sache tun, nämlich die Variable gesetzt localObject für dragItem gleich das resultierende Bild Bild .
Was bedeutet das?
Wenn Sie Draglokal "Drag & Drop" ausführen , dh innerhalb Ihrer Anwendung, müssen Sie nicht den gesamten mit itemProvider verknüpften Code durch asynchrones Abrufen von Daten durchgehen. Sie müssen dies nicht tun, Sie müssen nur localObject nehmen und es verwenden. Dies ist eine Art „Kurzschluss“ mit lokalem „Drag & Drop“ Drag.Der Code, den wir geschrieben haben, funktioniert beim „Ziehen“ Dragaußerhalb unserer Sammlung Collection Viewin andere Anwendungen. Wenn wir jedoch Draglokal „ziehen“ , können wir localObject verwenden . Als nächstes gebe ich ein Array von einem dragItem- Element zurück .Übrigens, wenn ich aus irgendeinem Grund nicht bekommen konnte Bild für diese Zelle Zelle , kehre ich leeres Array [] , das bedeutet , dass die „drag“ Dragabgebrochen. Neben lokalen Objekt localObject , können Sie den lokalen Kontext erinnern localContext für unsere
Neben lokalen Objekt localObject , können Sie den lokalen Kontext erinnern localContext für unsere DragSitzung die Sitzung . In unserem Fall wird es eine Sammlung von seiner Kollektion und es ist nützlich , um uns danach: Mit „Drag and Drop“
Mit „Drag and Drop“ Dragkönnen Sie weitere Elemente hinzufügen , Elemente diesen „drag and drop“, nur die Geste tun tippt auf sie. Als Ergebnis können Sie ziehenDragviele Gegenstände gleichzeitig. Und dies ist einfach mit einer anderen Delegatmethode zu implementieren , UICollectionViewDragDelegate , die der Methode itemsForeginning , einer Methode mit dem Namen itemsForAddingTo , sehr ähnlich ist . Die itemsForAddingTo- Methode sieht genauso aus wie die itemsForeginning- Methode und gibt genau das Gleiche zurück, da sie uns auch einen Indexpfad darüber gibt, was der Benutzer während des Drag Drag& Drop-Vorgangs „ aufgezeichnet “ hat , und ich muss nur das Bild aus der Zelle abrufen die der Benutzer "abgeklebt" und zurückgegeben. Gibt ein leeres Array [] von der itemsForAddingTo- Methode zurückbewirkt, dass die Tippgeste auf die übliche Weise interpretiert wird, dh als Auswahl dieser Zelle .Und das ist alles, was wir zum Ziehen und Ablegen benötigen
ein leeres Array [] von der itemsForAddingTo- Methode zurückbewirkt, dass die Tippgeste auf die übliche Weise interpretiert wird, dh als Auswahl dieser Zelle .Und das ist alles, was wir zum Ziehen und Ablegen benötigen Drag.Wir starten die Anwendung.Ich wähle das Bild "Venedig" aus, halte es eine Weile und beginne mich zu bewegen ... ... und wir können dieses Bild wirklich in die Anwendung ziehen
mich zu bewegen ... ... und wir können dieses Bild wirklich in die Anwendung ziehen Photos, da Sie das grüne Pluszeichen "+" in der oberen linken Ecke des "ziehbaren" Bildes sehen. Ich kann eine Tap- Geste auf ein anderes Artika-Bild aus der Sammlung ausführen Collection View... ... und jetzt können wir zwei Bilder in die Anwendung einfügen
... und jetzt können wir zwei Bilder in die Anwendung einfügen Photos: Da der
Da der PhotosMechanismus bereits in die Anwendung integriert istDrag & Dropdann funktioniert alles gut und es ist cool.Das "Ziehen" Dragund "Ablegen" des DropGaleriebilds in andere Anwendungen funktioniert für mich . Ich musste in meiner Anwendung nicht viel tun, außer das Bild als Array [UIDragItem] zu liefern . Dies ist eines der vielen großartigen Merkmale des Mechanismus Drag & Drop- es ist sehr einfach, ihn in beide Richtungen arbeiten zu lassen.DropBilder auf Sammlung zurücksetzenCollection View
Jetzt müssen wir einen DropTeil für meine Sammlung erstellen Collection View, damit wir Dropalle "gezogenen" Bilder IN dieser Sammlung "ausgeben" können. Ein "ziehbares" Bild kann von AUSSEN oder direkt IN dieser Sammlung "kommen".Um dies zu tun, werden wir das gleiche tun getan zu delegieren dragDelegate , also machen wir selbst, die selbst delegieren dropDelegate in dem Verfahren von dem viewDidLoad : Auch hier müssen wir an die Spitze unserer Klasse klettern ImageGalleryCollectionViewController und Protokoll - Implementierung überprüfen UICollectionViewDropDelegate :
Auch hier müssen wir an die Spitze unserer Klasse klettern ImageGalleryCollectionViewController und Protokoll - Implementierung überprüfen UICollectionViewDropDelegate : Sobald wir unser neues Protokoll hinzugefügt hatten, begann der Compiler erneut zu "beschweren", dass wir dieses Protokoll nicht implementiert haben. Wir klicken auf die Schaltfläche
Sobald wir unser neues Protokoll hinzugefügt hatten, begann der Compiler erneut zu "beschweren", dass wir dieses Protokoll nicht implementiert haben. Wir klicken auf die Schaltfläche Fixund die erforderlichen Methoden dieses Protokolls erscheinen vor uns. In diesem Fall werden wir darüber informiert, dass wir die performDrop- Methode implementieren müssen : Wir müssen dies tun, sonst wird kein „Reset“ durchgeführt
Wir müssen dies tun, sonst wird kein „Reset“ durchgeführt Drop. Tatsächlich werde ich die performDrop- Methode zuletzt implementieren , da es einige andere sehr empfohlene AppleMethoden gibt, die Sie für das DropTeil implementieren müssen . Dies ist canHandle und dropSessionDidUpdate : Wenn wir diese beiden Methoden implementieren, können wir ein wenig Greenbacks erhalten Plus - Zeichen „+“ , wenn wir Sie Bilder von außen auf unserer Sammlung ziehen
Wenn wir diese beiden Methoden implementieren, können wir ein wenig Greenbacks erhalten Plus - Zeichen „+“ , wenn wir Sie Bilder von außen auf unserer Sammlung ziehen ollection View, und darüber hinaus werden wir nicht versuchen , zu entleeren , was wir nicht verstehen.Lassen Sie uns implementieren canHandle . Wir müssen Ihre Version des Verfahrens canHandle , die für die Sammlung bestimmt ist ollection View., aber diese Methode ollection Viewsieht genau die gleiche Art und Weise wie ein ähnliches Verfahren zu dem herkömmlichen einem UIView , gibt es keine indexPath wir Rückkehr gerade brauchen. session.canLoadObjects (ofClass: UIImage.self) , und dass die Mittel dass ich das "Zurücksetzen" von Objekten dieses Cl akzeptiere PAS in meiner Sammlung ollection View: Dies reicht jedoch nicht aus, um das
Dies reicht jedoch nicht aus, um das DropBild Collection ViewAUSSERHALB in meine Sammlung zu "kopieren" .Wenn das „Reset“ Dropdas Bild innerhalb der Sammlung nimmt Collection View, wird der Benutzer seine eigenen Elemente reorganisieren Gegenstände durch den Mechanismus Drag & Drop, dann nur ein Bild einer UIImage und Implementierung des Verfahrens canHandle wie in der oben beschriebenen Weise aussehen wird.Wenn das "Dumping" des DropBildes jedoch AUSSEN erfolgt, sollten wir nur das "Ziehen und Ablegen" behandeln Drag, das das UIImage- Bild zusammen mit URLdiesem Bild ist, da wir die UIImage- Bilder nicht direkt speichern werdenim Modell. In diesem Fall werde ich zurückkehren wahr in dem Verfahren canHandle nur dann , wenn beide Bedingungen ein paar durchgeführt session.canLoadObjects (ofClass: NSURL.self) && session.canLoadObjects (ofClass: UIImage.self) : ich noch habe , um festzustellen , ob ich mit zu tun habe „Reset“ AUSSEN ODER INNEN. Ich werde es tun , mit Hilfe von berechneten Konstanten isself , für die die Berechnung kann ich diese Art der Sache in Verwendung
ich noch habe , um festzustellen , ob ich mit zu tun habe „Reset“ AUSSEN ODER INNEN. Ich werde es tun , mit Hilfe von berechneten Konstanten isself , für die die Berechnung kann ich diese Art der Sache in Verwendung Dropder Sitzung die Sitzung sowohl die lokale DragSitzung localDragSession . Diese lokale DragSitzung hat wiederum einen lokalen Kontext localContext .Wenn Sie sich erinnern, setzen wir diesen lokalen Kontext in der MethodeitemsForVeginning Drag Delegierten UICollectionViewDragDelegate : Ich werde die lokalen Kontext erforschen localContext auf Gleichheit in meiner Sammlung Collection . Richtig , TYPE von localContext ist Any , und ich muss ein Casting von TYPE Any mit dem Operator as durchführen. UICollectionView :
Ich werde die lokalen Kontext erforschen localContext auf Gleichheit in meiner Sammlung Collection . Richtig , TYPE von localContext ist Any , und ich muss ein Casting von TYPE Any mit dem Operator as durchführen. UICollectionView : Wenn der lokale Kontext (session.localDragSession .localContext als UICollectionView ??) Ist meine Sammlung Collection , die erweiterte Variable isSelf ist wahrund es gibt ein lokales "Zurücksetzen" IN meiner Sammlung. Wenn diese Gleichheit verletzt wird, handelt es sich um ein "Zurücksetzen"
Wenn der lokale Kontext (session.localDragSession .localContext als UICollectionView ??) Ist meine Sammlung Collection , die erweiterte Variable isSelf ist wahrund es gibt ein lokales "Zurücksetzen" IN meiner Sammlung. Wenn diese Gleichheit verletzt wird, handelt es sich um ein "Zurücksetzen" DropAUSSEN.Die canHandle- Methode gibt an , dass wir diese Art von Drag & Drop nur für Dragunsere Sammlung verarbeiten können Collection View. Ansonsten macht es keinen Sinn, von "Dumping" zu sprechen Drop.Wenn wir auf „Reset“ fortsetzen Drop, ist es noch bis zu dem Moment , dass der Benutzer die Finger vom Bildschirm heben wird , und es wird ein echter „Reset“ sein Drop, müssen wir berichten , iOSunter Verwendung des Verfahrens dropSessionDidUpdate Delegierten UICollectionViewDropDelegate über unser Angebot UIDropProposal zurückgesetzt zu implementieren Drop.Bei dieser Methode müssen wir einen DropSatz zurückgeben, der für das Operationsargument die Werte .copy oder .move oder .cancel oder .forbidden enthalten kann . Und dies sind alle Möglichkeiten, die wir im Normalfall haben, wenn wir uns mit einem regulären UIView befassen . Die Sammlung geht jedoch noch weiter und bietet an, das spezielle Angebot UICollectionViewDropProposal zurückzugeben , eine Klasse von UIDropProposal, mit der Sie zusätzlich zur Operationsoperation einen zusätzlichen Intent- Parameter für die Sammlung angeben können . ParameterCollection ViewsubclassCollection ViewMit Absicht wird der Sammlung mitgeteilt ,Collection Viewob das "verworfene" Element in einer vorhandenen Zelle platziert werden soll oder ob eine neue Zelle hinzugefügt werden soll . Sehen Sie den Unterschied? Im Fall der SammlungCollection Viewverkünden wir unsere Absicht, eine Absicht .In unserem Fall möchten wir immer eine neue Zelle hinzufügen, damit Sie sehen, wie hoch unser Intent- Parameter ist.Wir wählen den zweiten Konstruktor für UICollectionViewDropProposal aus : In unserem Fall möchten wir immer eine neue Zelle hinzufügen, und der Intent- Parameternimmtim Gegensatz dazuden Wert .insertAtDestinationIndexPath an.insertIntoDestinationIndexPath .
In unserem Fall möchten wir immer eine neue Zelle hinzufügen, und der Intent- Parameternimmtim Gegensatz dazuden Wert .insertAtDestinationIndexPath an.insertIntoDestinationIndexPath . Ich habe wieder die berechnete Konstante isSelf verwendet , und wenn es sich um eine Selbstreorganisation handelt , bewege ich .move , andernfalls kopiere ich .copy . In beiden Fällen verwenden wir .insertAtDestinationIndexPath , d.H. Das Einfügen neuer Zellen .Bisher habe ich die performDrop- Methode noch nicht implementiert, aber schauen wir uns an, was eine Sammlung bereits
Ich habe wieder die berechnete Konstante isSelf verwendet , und wenn es sich um eine Selbstreorganisation handelt , bewege ich .move , andernfalls kopiere ich .copy . In beiden Fällen verwenden wir .insertAtDestinationIndexPath , d.H. Das Einfügen neuer Zellen .Bisher habe ich die performDrop- Methode noch nicht implementiert, aber schauen wir uns an, was eine Sammlung bereitsCollection Viewmit dieser kleinen Informationtun kann, die wir ihr zur Verfügung gestellt haben.Ich ziehe das Bild ausSafarider SuchmaschineGoogleÜber diesem Bild wird ein grünes „+“ angezeigt, das darauf hinweist, dass unsere Bildergalerie nicht nur bereit ist, dieses Bild zu akzeptieren und zu kopieren URL, sondern auch einen Platz in der Sammlung bietet Collection View: Ich kann auf ein weiteres Bildpaar in
Ich kann auf ein weiteres Bildpaar in Safariund klicken Es werden bereits 3 "gezogene" Bilder angezeigt: Wenn ich jedoch meinen Finger hebe und
Wenn ich jedoch meinen Finger hebe und Dropdiese Bilder "fallen lasse " , werden sie nicht in unserer Galerie platziert, sondern kehren einfach zu ihren vorherigen Positionen zurück , da wir die performDrop- Methode noch nicht implementiert haben . Sie konnten sehen, dass die Sammlung
Sie konnten sehen, dass die Sammlung Collection Viewbereits weiß, was ich tun möchte.Die Sammlung Collection Viewist eine absolut wunderbare Sache für den Mechanismus.Drag & DropSie hat dafür sehr mächtige Funktionen. Wir haben sie kaum berührt, indem wir 4 Codezeilen geschrieben haben, und sie ist in der Wahrnehmung von "Zurücksetzen" bereits ziemlich weit gegangen Drop. Kehrenwir zum Code zurück und implementieren die performDrop- Methode . Bei dieser Methode kommen wir mit 4 Codezeilen nicht aus, da die performDrop- Methode etwas komplizierter, aber nicht zu viel ist.Wenn ein „Reset“
Bei dieser Methode kommen wir mit 4 Codezeilen nicht aus, da die performDrop- Methode etwas komplizierter, aber nicht zu viel ist.Wenn ein „Reset“ Drop, dann ist die Methode performDrop müssen wir unser Modell aktualisieren, die eine Galerie von Bildern Bildergalerie Combo Bild Bildern , und wir müssen unsere visuelle Sammlung aktualisieren Collection .Wir haben zwei verschiedene "Reset" -Szenarien Drop.Wenn Dropaus meiner collectionView- Sammlung ein "Zurücksetzen" erfolgt , muss ich das DropSammlungselement an einer neuen Stelle "zurücksetzen" und von der alten Stelle entfernen, da ich in diesem Fall dieses Sammlungselement verschiebe ( .move ). Dies ist eine triviale Aufgabe.Es wird ein „Reset“ Dropdurchgeführt wird aus einer anderen Anwendung heraus, dann müssen wir die Eigenschaft verwenden ItemProvider «gezogen» Element Element , um Daten abzurufen.Wenn wir Dropin der collectionView- Sammlung einen „Reset“ durchführen , stellt uns die Sammlung einen Koordinator- Koordinator zur Verfügung. In erster Linie haben wir berichtet , den Koordinator Koordinator , es destinationIndexPath , dh indexPath „-destination“, „Reset“ Drop, dass dort , wo wir werden ein „Reset“ . Aber destinationIndexPath kann gleich Null , so dass Sie die „rücksetzbar“ Bild in diesem Teil der Sammlung kann ziehen
Aber destinationIndexPath kann gleich Null , so dass Sie die „rücksetzbar“ Bild in diesem Teil der Sammlung kann ziehen Collection View, die zwischen einigen bestehenden Zellen kein Fleck Zellen , so dass es gut sein kann null . In diesem Fall erstelle ich einen Indexpfad mit dem Element 0th item im Abschnitt 0th section . Ich könnte jeden anderen Indexpfad auswählen , aber ich werde diesen Indexpfad standardmäßig verwenden.Jetzt wissen wir, wo wir den „Reset“ durchführen werden
Ich könnte jeden anderen Indexpfad auswählen , aber ich werde diesen Indexpfad standardmäßig verwenden.Jetzt wissen wir, wo wir den „Reset“ durchführen werden Drop. Wir müssen gehen durch alle „blow-off“ Artikel coordinator.items , vom Koordinator zur Verfügung gestellt Koordinator . Jedes Element aus dieser Liste hat einen UICollectionViewDropItem- TYP und kann uns sehr interessante Informationen liefern.Zum Beispiel, wenn ich bekommen kann sourceIndexPath von item.sourceIndexPath , werde ich genau wissen , was es ist „Drag and Drop“ Dragvon selbst erledigt ist, die Selbstund die Quelle des ZiehensDrag ist das Sammlungselement mit indexPath gleich sourceIndexPath : In diesem Fall muss ich nicht einmal auf localContext schauen , um herauszufinden, dass dieses "Ziehen und Ablegen" IN der Sammlung collectionView durchgeführt wurde .
ich nicht einmal auf localContext schauen , um herauszufinden, dass dieses "Ziehen und Ablegen" IN der Sammlung collectionView durchgeführt wurde . Wow!
Jetzt kenne ich die Quelle sourceIndexPath und das Ziel " destinationIndexPath " Drag & Drop, und die Aufgabe wird trivial. Alles , was ich tun muß , ist das Modell zu aktualisieren , so dass die Quelle und der „Zielpunkt“ umgekehrt wird , und aktualisieren Sie dann die Sammlung Collection , das das Element aus der Sammlung müssen entfernen sourceIndexPath und fügen Sie ihn in der Sammlung destinationIndexPath .Unser lokaler Fall ist der einfachste, da in diesem Fall der Mechanismus Drag & Dropnicht nur in derselben Anwendung, sondern in derselben collectionView- Sammlung funktioniert und ich alle erforderlichen Informationen über den Koordinatorkoordinator abrufen kann. Lassen Sie es uns in diesem einfachsten lokalen Fall implementieren: In unserem Fall benötige ich nicht einmal localObject , das ich zuvor beim Erstellen von dragItem "versteckt" habe und das ich jetzt aus dem "gezogenen" Element in der Elementauflistung im Formular item.localObject ausleihen kann . Wir werden es brauchen, wenn wir
In unserem Fall benötige ich nicht einmal localObject , das ich zuvor beim Erstellen von dragItem "versteckt" habe und das ich jetzt aus dem "gezogenen" Element in der Elementauflistung im Formular item.localObject ausleihen kann . Wir werden es brauchen, wenn wir DropBilder in den "Papierkorb" werfen, der sich in derselben Anwendung befindet, aber nicht dieselbe collectionView- Sammlung ist . Jetzt nur ich brauche zwei IndexPathes : Quelle sourceIndexPath und „Zielpunkt“ destinationIndexPath .Ich bekomme zuerst InformationenimageInfo über das Bild an der alten Stelle aus dem Modell, entfernen Sie es von dort. Und fügenanschließend in ein Array von Bildern meiner Modelle Bildergalerie Informationen Imageinfo ein Bild mit einem neuen Index destinationIndexPath.item . So habe ich mein Modell aktualisiert: Jetzt muss ich die collectionView- Sammlung selbst aktualisieren. Es ist sehr wichtig zu verstehen, dass ich nicht alle Daten in meiner collectionView- Sammlung mit reloadData () während des Drag & Drop-Prozessesüberladen möchte
Jetzt muss ich die collectionView- Sammlung selbst aktualisieren. Es ist sehr wichtig zu verstehen, dass ich nicht alle Daten in meiner collectionView- Sammlung mit reloadData () während des Drag & Drop-Prozessesüberladen möchteDrag, da dadurch die gesamte "Welt" unserer Bildergalerie neu installiert wird, was sehr schlecht ist. TUN SIE ES NICHT. Stattdessen werde ich aufräumen und Elemente einfügenElemente einzeln: Ich habe das Sammlungselement collectionView mit sourceIndexPath gelöscht und ein neues Sammlungselement mit destinationIndexPath eingefügt.Es sieht so aus, als ob dieser Code großartig funktioniert, aber in Wirklichkeit kann dieser Code Ihre Anwendung zum Absturz bringen. Der Grund dafür ist, dass Sie zahlreiche Änderungen an Ihrer collectionView- Sammlung vornehmen.In diesem Fall muss jeder Schritt zum Ändern der Sammlung normal mit dem Modell synchronisiert werden, was in unserem Fall nicht beobachtet wird, da beide Vorgänge gleichzeitig ausgeführt werden: Löschen und Einfügen. Daher die Sammlung collectionViewwird sich irgendwann in einem NICHT synchronisierten Zustand mit dem Modell befinden.Aber es gibt eine wirklich coole Möglichkeit, dies zu umgehen : Die collectionView- Auflistung verfügt über eine Methode namens performBatchUpdates mit einem Abschluss (
Ich habe das Sammlungselement collectionView mit sourceIndexPath gelöscht und ein neues Sammlungselement mit destinationIndexPath eingefügt.Es sieht so aus, als ob dieser Code großartig funktioniert, aber in Wirklichkeit kann dieser Code Ihre Anwendung zum Absturz bringen. Der Grund dafür ist, dass Sie zahlreiche Änderungen an Ihrer collectionView- Sammlung vornehmen.In diesem Fall muss jeder Schritt zum Ändern der Sammlung normal mit dem Modell synchronisiert werden, was in unserem Fall nicht beobachtet wird, da beide Vorgänge gleichzeitig ausgeführt werden: Löschen und Einfügen. Daher die Sammlung collectionViewwird sich irgendwann in einem NICHT synchronisierten Zustand mit dem Modell befinden.Aber es gibt eine wirklich coole Möglichkeit, dies zu umgehen : Die collectionView- Auflistung verfügt über eine Methode namens performBatchUpdates mit einem Abschluss ( closure). Innerhalb dieses Abschlusses kann ich eine beliebige Anzahl dieser deleteItems , insertItems , moveItems und alles, was ich möchte, platzieren: Jetzt werden deleteItems und insertItems als eine einzige Operation ausgeführt, und es wird nie an einer Synchronisierung Ihres Modells mit der Collection collectionView mangeln .Und schließlich müssen wir den Koordinator bitten, das „Zurücksetzen“ selbst zu implementieren und zu animieren
Jetzt werden deleteItems und insertItems als eine einzige Operation ausgeführt, und es wird nie an einer Synchronisierung Ihres Modells mit der Collection collectionView mangeln .Und schließlich müssen wir den Koordinator bitten, das „Zurücksetzen“ selbst zu implementieren und zu animieren Drop: Sobald Sie Ihren Finger vom Bildschirm heben, bewegt sich das Bild, alles geschieht gleichzeitig: „Zurücksetzen“, das Bild verschwindet an einem Ort und Aussehen an einem anderen.Versuchen wir, das Testbild „Venedig“ in unserer Bildergalerie an das Ende der ersten Zeile zu verschieben ...
Sobald Sie Ihren Finger vom Bildschirm heben, bewegt sich das Bild, alles geschieht gleichzeitig: „Zurücksetzen“, das Bild verschwindet an einem Ort und Aussehen an einem anderen.Versuchen wir, das Testbild „Venedig“ in unserer Bildergalerie an das Ende der ersten Zeile zu verschieben ... ... und es zurückzusetzen:
... und es zurückzusetzen: Wie wir wollten, wurde es am Ende der ersten Zeile platziert.
Wie wir wollten, wurde es am Ende der ersten Zeile platziert.Hurra!
Alles arbeitet!Jetzt werden wir uns NICHT mit dem lokalen Fall befassen, dh wenn das "Zurücksetzen" -Element AUSSERHALB kommt, dh aus einer anderen Anwendung.Um dies zu tun in dem Code schreiben wir sonst in Bezug auf die sourceIndexPath . Wenn wir nicht über sourceIndexPath verfügen , bedeutet dies, dass das "zurücksetzbare" Element von AUSSEN stammt und wir die Datenübertragung mit dem itemProver des zurücksetzbaren item.dragItem.itemProvider- Elements verwenden müssen : Wenn Sie AUSSEN "ziehen
Wenn Sie AUSSEN "ziehen Dragund ablegen " und " ablegen" ”DropWerden diese Informationen dann sofort verfügbar? Nein, Sie wählen ASYNCHRON Daten aus dem "gezogenen" Objekt aus. Aber was ist, wenn die Probe 10 Sekunden dauert? Was wird die Sammlung zu diesem Zeitpunkt tun ollection View? Darüber hinaus kommen die Daten möglicherweise nicht in der Reihenfolge an, in der wir sie angefordert haben. Dies zu handhaben ist nicht einfach und Appleschlug für ollection Viewdiesen Fall eine völlig neue Technologie für die Verwendung von Ersatzstoffen vor Placeholders.Sie platzieren einen Collection ViewPlatzhalter in Ihrer Sammlung Placeholder, und die Sammlung Collection Viewverwaltet alles für Sie. Wenn die Daten endgültig ausgewählt sind, müssen Sie den Platzhalter lediglich auffordern, Placeholderseinen placeholderContext- Kontext aufzurufenund sagen Sie ihm, dass Sie die Informationen erhalten haben. Aktualisieren Sie dann Ihr Modell und Ihren Kontext placeholderContext tauscht die Zelle AUTOMATISCH mit dem Platzhalter Placeholdergegen eine Ihrer Zellen aus , was dem Datentyp entspricht, den Sie erhalten haben.Alle diese Maßnahmen , die wir produzieren , durch einen Platzhalter Kontext zu schaffen placeholderContext , die einen Platzhalter steuert Placeholderund dass Sie von Koordinator erhalten Koordinator , „Reset“ zu fragen DropElement Element an einen Platzhalter Placeholder.Ich werde den Initialisierer für den Platzhalterkontext placeholderContext verwendenDas "wirft" DragItem in einen UICollectionViewDropPlaceholder : Das Objekt, das ich "werfen" werde,
Das Objekt, das ich "werfen" werde, Dropist item.dragItem , wobei item ein for- Element einer Schleife ist, da wir Dropviele koordinator.items werfen können . Wir "werfen" sie eins nach dem anderen. Also, item.dragItem - das ist , was wir „ziehen“ sind Dragund „werfen“ Drop. Das nächste Argument für diese Funktion ist der Platzhalter, und ich werde ihn mit dem UICollectionViewDropPlaceholder- Initialisierer erstellen : Dazu muss ich wissen, wo ich den Platzhalter einfügen werde
Dazu muss ich wissen, wo ich den Platzhalter einfügen werdePlaceholderd.h. insertionIndexPath sowie die Kennung der wiederverwendeten Zelle reuseIdentifier .Das insertionIndexPath- Argument entspricht offensichtlich dem destinationIndexPath . Es ist der IndexPath zum Platzieren des "gezogenen" Objekts und wird ganz am Anfang der performDropWith- Methode berechnet .Schauen wir uns nun die Zellen- ID von reuseIdentifier an . SIE müssen entscheiden, welcher Zelltyp Ihr Locator ist Placeholder. Im Brennpunkt Koordinator nicht „vorgerüstete“ Zelle - Zelle an einen PlatzhalterPlaceholder. Dass Sie eine Entscheidung über die Zelle nehmen müssen Zelle . Daher wird die Kennung der wiederverwendeten Zelle reuseIdentifiercell von Ihnen angefordert,storyboard damit sie als PROTOTYP verwendet werden kann.Ich werde es "DropPlaceholderCell" nennen, aber im Grunde könnte ich es wie auch immer nennen.Es ist nur ein String String , die ich auf meinem verwenden werde storyboarddiese Sache zu schaffen.Gehen Sie zurück zu unserer storyboardund erstellen Sie eine Zellzelle für den Platzhalter Placeholder. Dazu müssen wir nur eine Sammlung auswählen Collection Viewund untersuchen. Im allerersten Feld Itemswechsle ich 1zu2. Dadurch entsteht für uns sofort eine zweite Zelle, die eine exakte Kopie der ersten ist. Wir wählen unsere neue Zelle aus
Wir wählen unsere neue Zelle aus ImageCell, setzen den Bezeichner " DropPlaceholderCell", löschen alle UIElemente von dort , einschließlich Image View, da dieser PROTOTYP verwendet wird, wenn das Bild noch nicht angekommen ist. Wir fügen dort einen neuen Aktivitätsindikator aus der Objektpalette hinzu Activity Indicator, der sich dreht und die Benutzer darüber informiert, dass ich einige "Zurücksetzen" -Daten erwarte. Ändern Sie auch die Hintergrundfarbe Backgroundzu verstehen , dass , wenn „Reset“ von außen Bild funktioniert genau diese Zelle Zelle als Prototypen: Neben der Art der neuen Zelle sollte nicht ImageCollectionVewCell, weil es keine Bilder darin geben wird. Ich werde diese Zelle zu einer normalen UIollectionCiewCell TYPE- Zelle machen , da wir keine
Neben der Art der neuen Zelle sollte nicht ImageCollectionVewCell, weil es keine Bilder darin geben wird. Ich werde diese Zelle zu einer normalen UIollectionCiewCell TYPE- Zelle machen , da wir keine Outletsfür die Steuerung benötigen : Konfigurieren Sie den Aktivitätsindikator
Konfigurieren Sie den Aktivitätsindikator Activity Indicatorso, dass er von Anfang an animiert wird und ich nichts in den Code schreiben müsste, um ihn zu starten. Klicken Sie dazu auf die Option Animating: Und das ist alles. Also haben wir alle Einstellungen für diese Zelle vorgenommen
Und das ist alles. Also haben wir alle Einstellungen für diese Zelle vorgenommen DropPlaceholderCellund kehren zu unserem Code zurück. Jetzt haben wir einen großartigen Locator Placeholderbereit.Alles, was wir tun müssen, ist, die Daten abzurufen. Wenn die Daten empfangen werden, teilen wir dem placeholderContext einfach diesen Kontext mit und er tauscht den Platzhalter ausPlaceholderund unsere "native" Zelle mit Daten, und wir werden Änderungen am Modell vornehmen.Ich werde EIN Objekt "laden", das mein Element sein wird, indem ich die Methode loadObject (ofClass: UIImage.self) (Singular) verwende. Ich verwende den Code item.dragItem.itemProvider Anbieter ItemProvider , welche Datenelemente liefert Artikel asynchron. Es ist klar, dass wenn iitemProvider verbunden ist , wir das iitem-Objekt "reset" außerhalb dieser Anwendung erhalten. Das Folgende ist die Methode loadObject (ofClass: UIImage.self) (Singular): Dieser bestimmte Abschluss wird NICHT ausgeführt
Dieser bestimmte Abschluss wird NICHT ausgeführtmain queue. Und leider mussten wir Schalter main queuemit DispatchQueue.main.async {} , um „fangen“ das Seitenverhältnis des Bildes auf eine lokale Variable aspectratio .Wir haben wirklich zwei lokale Variablen imageURL und AspectRatio eingeführt ... ... und wir werden sie beim Laden des Image- Images und der URL- URL "abfangen" :
... und wir werden sie beim Laden des Image- Images und der URL- URL "abfangen" : Wenn beide lokalen Variablen imageURL und AspectRatio nicht Null sind , werden wir den Platzhalter- Kontext- Platzhalter- Kontext mit der Methode commitInsertion fragenGeben Sie uns die Möglichkeit, unser imageGallery- Modell zu ändern :
Wenn beide lokalen Variablen imageURL und AspectRatio nicht Null sind , werden wir den Platzhalter- Kontext- Platzhalter- Kontext mit der Methode commitInsertion fragenGeben Sie uns die Möglichkeit, unser imageGallery- Modell zu ändern : In diesem Ausdruck haben wir insertionIndexPath - dies ist der einzufügende indexPath , und wir ändern unser imageGallery- Modell . Das ist alles, was wir tun müssen, und diese Methode ersetzt AUTOMATISCH einen Platzhalter
In diesem Ausdruck haben wir insertionIndexPath - dies ist der einzufügende indexPath , und wir ändern unser imageGallery- Modell . Das ist alles, was wir tun müssen, und diese Methode ersetzt AUTOMATISCH einen Platzhalter Placeholderdurch eine Zelle, indem sie die normale cellForItemAt- Methode aufruft .Beachten Sie, dass insertionIndexPath sich stark von destinationIndexPath unterscheiden kann . Warum?
Da die Datenerfassung natürlich 10 Sekunden dauern kann, ist dies unwahrscheinlich, kann jedoch 10 Sekunden dauern. In dieser Zeit Collection Viewkann in der Sammlung viel passieren. Können neue Zellen hinzufügen Zellen geschieht alles schnell genug.Verwenden Sie IMMER insertionIndexPath und NUR insertionIndexPath , um Ihr Modell zu aktualisieren.Wie aktualisieren wir unser Modell?Wir fügen in das Array imageGallery.images Struktur imagemodel , bestehend aus dem Seitenverhältnis aspectratio und Bild - URL imageURL , der uns die entsprechenden zurück nach Anbietern .Dadurch wird unser imageGallery- Modell aktualisiert , und die Methode commitInsertion erledigt den Rest für uns. Sie müssen nichts mehr tun, keine Einfügungen, keine Löschungen, nichts davon. Und da wir uns in einer Schließung befinden, müssen wir uns natürlich selbst hinzufügen . .
 Wenn wir aus irgendeinem Grunde nicht in der Lage sind das Seitenverhältnis zu erhalten aspectratio und
Wenn wir aus irgendeinem Grunde nicht in der Lage sind das Seitenverhältnis zu erhalten aspectratio und URLBild imageURL aus den entsprechenden durch Anbieter , könnte ein Fehler empfangen wurde Fehler anstelle von Anbietern , müssen wir wissen lassen, sie aus dem Zusammenhang placeholderContext , müssen Sie diese Platzhalter zerstören Placeholder, weil wir alle gleich sind, können wir nicht Andere Daten abrufen: Eine Sache, die Sie beachten sollten, ist,
Eine Sache, die Sie beachten sollten, ist, URLsdass sie von Orten wie diesem stammen Google. In Wirklichkeit benötigen sie kleinere Transformationen, um „sauber“ zu werden.URLfür das Bild. Wie dieses Problem gelöst wird, können Sie dieser Demoanwendung in einer Datei Utilities.swiftauf Github entnehmen .Daher verwenden URLwir beim Empfang eines Bildes die Eigenschaft imageURL aus der URL- Klasse : Und das ist alles, was Sie tun müssen, um AUSSERHALB etwas in der Sammlung zu akzeptieren
Und das ist alles, was Sie tun müssen, um AUSSERHALB etwas in der Sammlung zu akzeptieren Collection View.Lassen Sie es uns in Aktion sehen. Wir starten gleichzeitig in einem Multitasking-Modus unsere Demo-Anwendung ImageGalleryund Safarimit einer Suchmaschine Google. In Googlesuchen wir nach Bildern zum Thema "Dawn" (Sonnenaufgang). In Safaribereits gebautDrag & DropDer Mechanismus, damit wir eines dieser Bilder auswählen, lange halten, ein wenig verschieben und in unsere Bildergalerie ziehen können. Das Vorhandensein eines grünen Pluszeichens "+" zeigt an, dass unsere Anwendung bereit ist, ein Bild eines Drittanbieters zu akzeptieren und es an dem vom Benutzer angegebenen Ort in Ihre Sammlung zu kopieren. Nachdem wir es „zurückgesetzt“ haben, dauert es einige Zeit, bis das Bild heruntergeladen ist. Zu diesem Zeitpunkt funktioniert es
Das Vorhandensein eines grünen Pluszeichens "+" zeigt an, dass unsere Anwendung bereit ist, ein Bild eines Drittanbieters zu akzeptieren und es an dem vom Benutzer angegebenen Ort in Ihre Sammlung zu kopieren. Nachdem wir es „zurückgesetzt“ haben, dauert es einige Zeit, bis das Bild heruntergeladen ist. Zu diesem Zeitpunkt funktioniert es Placeholder: Nach Abschluss des Downloads wird das Bild „Zurücksetzen“ an der richtigen Stelle platziert und
Nach Abschluss des Downloads wird das Bild „Zurücksetzen“ an der richtigen Stelle platziert und Placeholderverschwindet: Wir können die Bilder weiterhin „zurücksetzen“ und in unserem Bild ablegen Sammlungen von noch mehr Bildern:
Wir können die Bilder weiterhin „zurücksetzen“ und in unserem Bild ablegen Sammlungen von noch mehr Bildern: Nach dem "Zurücksetzen"
Nach dem "Zurücksetzen" Placeholder: Infolgedessen wird unsere Bildergalerie mit neuen Bildern gefüllt:
Infolgedessen wird unsere Bildergalerie mit neuen Bildern gefüllt: Nun , da klar ist , dass wir Fotos machen können von außen, wir brauchen nicht das Testbild, und wir werden entfernen:
Nun , da klar ist , dass wir Fotos machen können von außen, wir brauchen nicht das Testbild, und wir werden entfernen: Unsere viewDidLoad wird sehr einfach: es ist , dass wir unser tun
Unsere viewDidLoad wird sehr einfach: es ist , dass wir unser tun Controller Dragund Dropdelegieren und fügen Erkenner Geste Prise , die die Anzahl der Bilder pro Zeile reguliert: Natürlich können wir einen Cache für imageCache- Bilder hinzufügen :
Natürlich können wir einen Cache für imageCache- Bilder hinzufügen : Wir füllen imageCache beim "Zurücksetzen"
Wir füllen imageCache beim "Zurücksetzen" Dropin der performDrop- Methode ... und beim Abrufen aus dem "Netzwerk" in der benutzerdefinierten ImageCollectionViewCell- Klasse :
und beim Abrufen aus dem "Netzwerk" in der benutzerdefinierten ImageCollectionViewCell- Klasse : Und wir verwenden den imageCache- Cache beim Abspielen einer ZelleZelle unserer Bildergalerie in der benutzerdefinierten Klasse ImageCollectionViewCell :
Und wir verwenden den imageCache- Cache beim Abspielen einer ZelleZelle unserer Bildergalerie in der benutzerdefinierten Klasse ImageCollectionViewCell : Jetzt beginnen wir mit einer leeren Sammlung ...
Jetzt beginnen wir mit einer leeren Sammlung ... ... und legen dann ein neues Bild in unserer Sammlung ab ...
... und legen dann ein neues Bild in unserer Sammlung ab ... ... das Bild wird hochgeladen und
... das Bild wird hochgeladen undPlaceholderfunktioniert ... ... und das Bild erscheint an der richtigen Stelle:
... und das Bild erscheint an der richtigen Stelle: Wir füllen unsere Sammlung weiterhin AUSSEN:
Wir füllen unsere Sammlung weiterhin AUSSEN: Kommt Das Laden von Bildern
Kommt Das Laden von BildernPlaceholdersfunktioniert ... Und die Bilder erscheinen an der richtigen Stelle:
Und die Bilder erscheinen an der richtigen Stelle: Wir können also viel mit unserer Bildergalerie tun: Füllen Sie sie AUSSEN, organisieren Sie Elemente INNEN neu, teilen Sie Bilder mit anderen Anwendungen Niyami.Wir müssen ihr nur beibringen, wie man unnötige Bilder durch „Zurücksetzen“ beseitigt
Wir können also viel mit unserer Bildergalerie tun: Füllen Sie sie AUSSEN, organisieren Sie Elemente INNEN neu, teilen Sie Bilder mit anderen Anwendungen Niyami.Wir müssen ihr nur beibringen, wie man unnötige Bilder durch „Zurücksetzen“ beseitigtDropim "Mülleimer" in der Navigationsleiste rechts. Wie im Abschnitt „Funktionen der Demoanwendung für Bildergalerien“ beschrieben, wird der „Papierkorb“ durch die GabageView- Klasse dargestellt , die von UIView erbt, und wir müssen ihm beibringen, Bilder aus unserer Sammlung zu akzeptieren ollection View.Setzen Sie die DropBilder der Galerie in den Papierkorb zurück.
Sofort vom Ort - zum Steinbruch. Ich will hinzufügen GabageView „Interaktion“ Interaktion und es wird UIDropInteraction , da ich versuche zu „reset“ ein Droppaar Dinge. Alle müssen wir sicherstellen , dass UIDropInteraction , dieser Delegat die Delegierten , und ich werde selbst ernennen, die sich selbst , dieser Delegat der Delegierte : Natürlich unsere Klasse GabageView bestätigen , dass wir ein Protokoll implementieren UIDropInteractionDelegate :
Natürlich unsere Klasse GabageView bestätigen , dass wir ein Protokoll implementieren UIDropInteractionDelegate : Alles , was wir tun müssen, um damit es funktioniert
Alles , was wir tun müssen, um damit es funktioniert Drop, Dies dient zur Implementierung der uns bereits bekannten canHandle- Methoden .sessionDidUpdate und performDrop . Im Gegensatz zu ähnlichen Methoden für die Sammlung
Im Gegensatz zu ähnlichen Methoden für die SammlungCollection Viewverfügen wir jedoch nicht über zusätzliche Informationen in Form eines Indexpfads der Deponie.Lassen Sie uns diese Methoden implementieren.Innerhalb der Methode canHandle nur die „Drag and Drop“ verarbeitet werdenDrag, die das Bild repräsentieren ein UIImage . Daher werde ichnur true zurückgeben, wenn session.canLoadObjects (ofClass: UIImage.self) : In der canHandle- Methodesagen Sie im Wesentlichen nur, wenn das "ziehbare" Objekt kein UIImage- Bild istDann macht es keinen Sinn, das "Zurücksetzen" fortzusetzen und nachfolgende Methoden aufzurufen.Wenn das "ziehbare" Objekt ein UIImage- Image ist , führen wir die sessionDidUpdate- Methode aus . Bei dieser Methode müssen wir lediglich unser UIDropProposal- Angebot zum Zurücksetzen zurückgeben
In der canHandle- Methodesagen Sie im Wesentlichen nur, wenn das "ziehbare" Objekt kein UIImage- Bild istDann macht es keinen Sinn, das "Zurücksetzen" fortzusetzen und nachfolgende Methoden aufzurufen.Wenn das "ziehbare" Objekt ein UIImage- Image ist , führen wir die sessionDidUpdate- Methode aus . Bei dieser Methode müssen wir lediglich unser UIDropProposal- Angebot zum Zurücksetzen zurückgeben Drop. Und ich bin bereit, nur das "gezogene" LOKALE Objekt des UIImage-Typs des Bildes zu akzeptieren , das Dropüberall in meiner GarbageView "abgelegt" werden kann . Mein GarbageView interagiert nicht mit Bildern, die AUSSEN ausgegeben werden. Ich analysiere also mit der Variablen session.localDragSessionob es ein lokales "Zurücksetzen" Dropgibt und ich den "Zurücksetzen" -Satz in Form des UIDropProposal- Konstruktors mit dem Operationsargument zurücknehme , das den Wert .copy annimmt , da IMMER LOKALES "Ziehen und Ablegen" Dragin meiner Anwendung aus der Sammlung stammt Collection View. Wenn "Drag Drag& Drop" und "Zurücksetzen" DropAUSSEN auftreten, gebe ich den Satz "Zurücksetzen" in Form des UIDropProposal- Konstruktors mit dem Operationsargument zurück , das den Wert .fobbiden annimmt, dh "verboten", und wir erhalten ein Verbotszeichen "Zurücksetzen" anstelle des grünen Pluszeichens . Kopieren eines UIImage- BildesWir simulieren eine Verringerung der Skalierung auf fast 0, und wenn das "Zurücksetzen" erfolgt, entfernen wir dieses Bild aus der Sammlung
Kopieren eines UIImage- BildesWir simulieren eine Verringerung der Skalierung auf fast 0, und wenn das "Zurücksetzen" erfolgt, entfernen wir dieses Bild aus der Sammlung Collection View.Um die Illusion zu erzeugen, dass Bilder für den Benutzer in der "Mülltonne" "abgeladen und verschwunden" werden, verwenden wir die für uns neue VorschauForDropping- Methode , mit der wir das "Dumping" Dropan einen anderen Ort umleiten und gleichzeitig das "abgelegte" Objekt während der Animation transformieren können: Bei dieser Methode erhalten wir mithilfe des UIDragPreviewTarget- Initialisierers eine neue Vorschau für das zu löschende Zielobjekt und leiten es mithilfe der retargetedPreview- Methode uman einen neuen Ort, an die „Mülltonne“, deren Skalierung auf fast Null reduziert ist :
Bei dieser Methode erhalten wir mithilfe des UIDragPreviewTarget- Initialisierers eine neue Vorschau für das zu löschende Zielobjekt und leiten es mithilfe der retargetedPreview- Methode uman einen neuen Ort, an die „Mülltonne“, deren Skalierung auf fast Null reduziert ist : Wenn der Benutzer einen Finger nach oben hebt, erfolgt ein „Zurücksetzen“
Wenn der Benutzer einen Finger nach oben hebt, erfolgt ein „Zurücksetzen“ Drop, und ich (wie GarbageView ) erhalte eine performDrop- Nachricht . In der performDrop- Nachricht führen wir den eigentlichen „Reset“ durch Drop. Ehrlich gesagt interessiert uns das Bild, das auf GarbageView selbst abgelegt wurde , nicht mehr, da wir es praktisch unsichtbar machen werden. Höchstwahrscheinlich Dropsignalisiert die Tatsache, dass der „Reset“ abgeschlossen ist, dass wir dieses Bild aus der Sammlung entfernen Collection View. Um dies zu erreichen, müssen wir die Sammlung selbst und den Sammlungsindexpfad kennenverworfenes Bild darin. Woher können wir sie bekommen?Da der Prozess Drag & Dropin einer einzigen Anwendung kommt, ist es uns zur Verfügung alle lokalen: lokale DragSitzung localDragSession unsere DropSitzung der Sitzung , der lokale Kontext localContext , die unsere Sammlung ist sollectionView und lokale Objekt localObject , die wir selbst zurückgesetzt Bild ist tun Bild von „Galerie“ oder indexPath . Aus diesem Grunde können wir in der Methode bekommen performDrop Klasse GarbageView Sammlung Sammlung , und deren Verwendungdatasource wie ImageGalleryCollectionViewController und Modell Bildergalerie unsereController, können wir eine Reihe von Bildern erhalten Bilder TYPE [ImageModel]: Mit Hilfe der lokalen
Mit Hilfe der lokalenDragSitzung localDragSession unsererDropSitzung Session konnten wir alle die „ziehen“ bekommen auf GarbageView Drag Elemente Elemente , und es kann eine Menge sein, wie wir wissen, und Alle von ihnen sind Bilder unserer collectionView-Sammlung . ErstellenDragElementen dragItems unserer SammlungCollection Viewhaben wir für jeden „drag“ vorgesehenDragElementdragItem lokales Objekt localObject , der das Bild ist Bild , aber es istwir nicht beiinternen Reorganisation Sammlung in handlichen kommen Collection , aber die „Reset“ Bildergalerie „Abfalleimer“ wir in den lokalen Einrichtung dringend brauchen localObject „drag“ Objekt dragItem , nach dieserZeit Wir haben keinen Koordinator , der so großzügig Informationen darüber austauscht, was in der collectionView- Sammlung geschieht. Deshalb wollen wir das lokale Objekt localObject Index war indexPath in der BildArray - Bilder unserer ModelleimageGallery . Nehmen Sie die notwendigen Änderungen der Methode dragItems (bei indexPath: IndexPath) Klasse ImageGalleryCollectionViewController : Jetzt können wir alle „pretaskivaemogo“ Element nehmen Element es localObject , die der Index indexPath in der BildArray - Bilder unserer Modelle Bildergalerie , und an die ArrayIndizes senden Indizes und Array indexPahes delete Bilder:
Jetzt können wir alle „pretaskivaemogo“ Element nehmen Element es localObject , die der Index indexPath in der BildArray - Bilder unserer Modelle Bildergalerie , und an die ArrayIndizes senden Indizes und Array indexPahes delete Bilder: die Indexarray Wissen Indizes und Array indexPahes delete Bilder in den Verfahren performBatchUpdatesSammlung Sammlung wir alle gelöschten Bilder von Models entfernen Bilder und aus der Sammlung der Sammlung :
die Indexarray Wissen Indizes und Array indexPahes delete Bilder in den Verfahren performBatchUpdatesSammlung Sammlung wir alle gelöschten Bilder von Models entfernen Bilder und aus der Sammlung der Sammlung : Führen Sie die Anwendung, füllen Sie die Galerie mit neuen Bildern:
Führen Sie die Anwendung, füllen Sie die Galerie mit neuen Bildern: ein Paar von Bildern auswählen , die wir von unserer Galerie entfernen möchten ...
ein Paar von Bildern auswählen , die wir von unserer Galerie entfernen möchten ... ... „werfen“ , um sie auf das Symbol mit der „Mülltonne“ ...
... „werfen“ , um sie auf das Symbol mit der „Mülltonne“ ... Sie reduziert fast auf 0 ...
Sie reduziert fast auf 0 ... ... und verschwinden aus der Sammlung
... und verschwinden aus der Sammlung Collection View, versteckt im "Mülleimer":
Speichern von Bildern zwischen den Starts.
Um die Bildergalerie zwischen den Läufen zu speichern, verwenden wir UserDefaults , nachdem wir unser Modell in ein JSONFormat konvertiert haben. Um dies zu tun, wird fügen wir unseren ControllerVariable var defailts ... ... und im Modell Bilddatenbank und ImageModel Protokoll Kodierbare :
... und im Modell Bilddatenbank und ImageModel Protokoll Kodierbare : String String Arrays von der Array , der URL und Doppel setzen bereits das Protokoll Kodierbare , so dass wir an die Arbeit Codierung nicht zu bekommen , sonst haben , etwas zu tun und Dekodieren in ImageGallery- Modelle im
String String Arrays von der Array , der URL und Doppel setzen bereits das Protokoll Kodierbare , so dass wir an die Arbeit Codierung nicht zu bekommen , sonst haben , etwas zu tun und Dekodieren in ImageGallery- Modelle im JSONFormat.Wie bekommen wir die JSONVersion von ImageGallery ?Erstellen Sie dazu eine berechnete Variable var json , die das Ergebnis eines Versuchs zurückgibt, sich selbst mit JSONEncoder.encode () in das folgende JSONFormat zu konvertieren: Und das ist alles. Entweder werden Daten als Ergebnis der Konvertierung von self in format zurückgegeben
Und das ist alles. Entweder werden Daten als Ergebnis der Konvertierung von self in format zurückgegeben JSON, oder nil, wenn diese Konvertierung fehlschlägt, obwohl letzteres niemals geschieht, da dieser TYP zu 100% codierbar ist . Die optionale Variable json wird nur aus Symmetriegründen verwendet.Jetzt haben wir eine Art und Weise Modelle zu konvertieren Bilddatenbank in Daten - Format JSON. Hat die json- Variable TYPE- Daten? was in UserDefaults gespeichert werden kann .Stellen Sie sich nun vor, wir haben es irgendwie geschafft, die JSON-JSON Daten abzurufen , und ich möchte daraus unser Modell, eine Instanz der ImageGallery- Struktur, neu erstellen . Für diese sehr leicht zu schreiben initializer Bildergalerie sind die Eingabeargumente die Daten der json . Dieser Initialisierer ist ein "fallender" Initialisierer (JSONfailable) Wenn es nicht initialisiert wird, es „fällt“ und kehrt nil : Ich bin nur eine neuer Wert bekomme newValue von den Decodern JSONDecoder und versuche , die Daten zu dekodieren die json , die zu meinen initializer übertragen werden, und dann ordnet sie das Selbst .Wenn ich das geschafft habe, bekomme ich eine neue Instanz von ImageGallery , aber wenn mein Versuch fehlschlägt, gebe ich null zurück , da meine Initialisierung "fehlgeschlagen" ist.Ich muss sagen, dass wir hier viel mehr Gründe haben, um zu „scheitern“ (
Ich bin nur eine neuer Wert bekomme newValue von den Decodern JSONDecoder und versuche , die Daten zu dekodieren die json , die zu meinen initializer übertragen werden, und dann ordnet sie das Selbst .Wenn ich das geschafft habe, bekomme ich eine neue Instanz von ImageGallery , aber wenn mein Versuch fehlschlägt, gebe ich null zurück , da meine Initialisierung "fehlgeschlagen" ist.Ich muss sagen, dass wir hier viel mehr Gründe haben, um zu „scheitern“ ( fail), weil es durchaus möglich ist, dass die json-JSON Datenkann verwöhnt oder leer sein, all dies kann zum "Fall" ( fail) des Initialisierers führen.Jetzt können wir die READ implementieren JSONDaten und Wiederherstellungsmodell Bildergalerie die Methode viewWillAppear unsere Controller... ... sowie ein Eintrag im Beobachter didSet {} Eigenschaften Bildergalerie :
... sowie ein Eintrag im Beobachter didSet {} Eigenschaften Bildergalerie : Lassen Sie uns die Anwendung ausführen und füllen unsere Galerie von Bildern:
Lassen Sie uns die Anwendung ausführen und füllen unsere Galerie von Bildern: Wenn wir die Anwendung zu schließen und wieder öffnen, können wir unsere bisherigen Galerie sehen In UserDefaults gespeicherte Bilder .
Wenn wir die Anwendung zu schließen und wieder öffnen, können wir unsere bisherigen Galerie sehen In UserDefaults gespeicherte Bilder .Fazit
Dieser Artikel zeigt am Beispiel einer sehr einfachen Demo-Anwendung „Image Gallery“, wie einfach es ist, Technologie Drag & Dropin eine iOSAnwendung zu integrieren . Dies ermöglichte es, die Bildergalerie vollständig zu bearbeiten, neue Bilder aus anderen Anwendungen dort zu „werfen“, vorhandene zu verschieben und unnötige zu löschen. Und auch, um in der Galerie gesammelte Bilder an andere Anwendungen zu verteilen.Natürlich möchten wir viele solcher thematischen malerischen Bildersammlungen erstellen und direkt auf dem iPad oder iCloud Drive speichern. Dies kann erfolgen, wenn jede solche Galerie als permanent gespeichertes UIDocument interpretiert wird. Eine solche Interpretation ermöglicht es uns, zur nächsten Abstraktionsebene aufzusteigen und eine Anwendung zu erstellen, die mit Dokumenten arbeitet. In einer solchen Anwendung werden Ihre Dokumente von der DocumentBrowserViewController- Komponente angezeigt, die der Anwendung sehr ähnlich ist Files. Auf diese Weise können Sie UIDocument- Bilder vom Typ „Bildergalerie“ sowohl auf Ihrem als auch auf Ihrem Bildschirm erstellen iPadund iCloud Drivedas gewünschte Dokument zum Anzeigen und Bearbeiten auswählen.Dies ist jedoch das Thema des nächsten Artikels.PS Der Code der Demo-Anwendung vor Drag & Dropund nach der Implementierung des Mechanismus befindet sich auf Github .