iOS 11 hat iOS, insbesondere für das iPad, dank Drag and Drop zu einer echten Multitasking-Plattform entwickelt. Dies verspricht, die Grenzen zwischen Apps zu verwischen, so dass Inhalte problemlos geteilt werden können. IOS 11 nutzt Multi-Touching und ermöglicht die natürliche und intuitive Verschiebung von Inhalten, wodurch die mobilen Geräte von Apple mit der Fülle ihrer Desktop- und Laptopbenutzer gleichwertiger werden.
Mit dieser lang erwarteten Funktion können Sie Elemente an einen anderen Ort in derselben Anwendung oder in eine andere Anwendung ziehen. Dies funktioniert entweder über eine Split-Screen-Anordnung oder über das Dock mit einer kontinuierlichen Geste. Darüber hinaus können Benutzer nicht nur einzelne Elemente auswählen, sondern können mehrere Objekte gleichzeitig ziehen. Viele Apps, einschließlich System-Apps wie Fotos und Dateien, nutzen die Mehrfachauswahl und das Ziehen mehrerer Dateien.
In diesem Lernprogramm werden Sie mit Drag & Drop vertraut gemacht. Anschließend lernen Sie die Architektur und Strategie der Verwendung des neuen Drag & Drop-SDK in einer tabellenansichtgestützten App kennen. Ich möchte Entwicklern wie Ihnen helfen, Ihre Apps an das aufkommende Verhalten der Benutzeroberfläche anzupassen, das in zukünftigen iOS-Apps zum Standard wird.
In diesem Tutorial behandeln wir Folgendes:
In der zweiten Hälfte dieses Tutorials werden wir die praktischen Schritte durchgehen, die eine einfache Tabellensicht-App ermöglichen, die Drag & Drop-Funktionen nutzen kann. Beginnen wir mit einer der Standardvorlagen für Tabellenansichten von Apple, die beim Erstellen eines neuen Projekts in Xcode verfügbar sind 9. Klonen Sie das GitHub-Repo des Tutorials, wenn Sie mitmachen möchten.
Dieses Tutorial setzt voraus, dass Sie Erfahrung als iOS-Entwickler haben und UIKit-Bibliotheken in Swift oder Objective-C verwendet haben, einschließlich UITableView
, und dass Sie mit Delegierten und Protokollen vertraut sind.
Unter Verwendung der Apple-Nomenklatur wird ein visuelles Element vom Ursprungsort gezogen und am Zielort abgelegt. Dies wird als Drag-Aktivität bezeichnet. Die Aktivität findet entweder in einer einzelnen App (iPad und iPhone unterstützt) oder in zwei Apps (nur auf dem iPad) statt..
Während eine Drag-Sitzung ausgeführt wird, sind sowohl die Quell- als auch die Ziel-App weiterhin aktiv und werden wie üblich ausgeführt, um Benutzerinteraktionen zu unterstützen. Im Gegensatz zu macOS unterstützt iOS mehrere gleichzeitige Drag-Aktivitäten, indem mehrere Finger verwendet werden.
Aber konzentrieren wir uns auf ein einzelnes Ziehelement und darauf, wie ein Versprechen als Vertrag für seine Datendarstellungen verwendet wird.
Jedes Drag-Element kann als Versprechen betrachtet werden, eine enthaltene Datendarstellung, die von einer Quelle an ihr Ziel gezogen und dort abgelegt wird. Das Drag-Element verwendet einen Elementanbieter und füllt seinen RegisteredTypeIdentifiers
mit einheitlichen Typkennungen, bei denen es sich um individuelle Datendarstellungen handelt, die er zusammen mit einem Vorschaubild (das visuell unter dem Berührungspunkt des Benutzers fixiert ist) an sein vorgesehenes Ziel liefern wird, wie unten dargestellt:
Das Ziehelement wird durch die erstellt UIDragInteractionDelegate
vom Ursprungsort aus und am Zielort über die UIDropInteractionDelegate
. Der Quellspeicherort muss dem entsprechen NSItemProviderWriting
Protokoll und der Zielort muss dem entsprechen NSItemProviderReading
Protokoll.
Dies ist eine grundlegende Übersicht über das Nominieren einer Ansicht als Drag-Element durch Versprechen. Sehen wir uns an, wie wir eine Ziehquelle aus einer Ansicht implementieren, bevor wir das Ablageziel festlegen.
Wir konzentrieren uns auf den ersten Teil des Drag & Drop - der Quelle zum Ziehen -, und müssen die folgenden Schritte ausführen, wenn der Benutzer eine Drag-Aktivität initiiert:
UIDragInterationDelegate
Protokoll.dragInteraction (_: itemsForBeginning :)
. Das erste, was Sie tun müssen, ist die Anpassung Ihrer nominierten Sicht an die UIDragInterationDelegate
Protokoll, indem Sie ein neues erstellen UIDragInteraction
Instanz und verknüpfen Sie es mit Ihrem ViewController
aus der Sicht addInteraction
Eigentum sowie sein Stellvertreter wie folgt:
let dragInteraction = UIDragInteraction (Delegat: dragInteractionDelegate) view.addInteraction (dragInteraction)
Nachdem Sie Ihre Ziehquelle deklariert haben, fahren Sie mit der Erstellung eines Ziehelements fort, das im Wesentlichen ein Versprechen der Datendarstellung darstellt, indem Sie die Delegat-Methode implementieren dragInteraction (_: itemsForBeginning :)
, Das System ruft das System auf, um ein Array mit einem oder mehreren Ziehelementen zurückzugeben, um die Elementeigenschaft der Ziehsitzung zu füllen. Im folgenden Beispiel wird ein erstellt NSItemProvider
von einem Image-Versprechen, bevor ein Array von Datenelementen zurückgegeben wird:
func dragInteraction (_action: UIDragInteraction, itemsForBeginning-Sitzung: UIDragSession) -> [UIDragItem] guard let imagePromise = imageView.image else return [] // Durch die Rückgabe eines leeren Arrays deaktivieren Sie das Ziehen. let provider = NSItemProvider (object: imagePromise) let item = UIDragItem (itemProvider: provider) gibt [item] zurück.
Die obige Delegatmethode reagiert auf eine Ziehanforderung, die ausgelöst wird, wenn der Benutzer das Element mit dem Gestenerkenner (UIGestureRecognizer
) Senden einer Zieh-Start-Nachricht an das System. Dies ist, was im Wesentlichen die "Drag-Sitzung" initialisiert.
Als Nächstes fahren wir mit der Implementierung des Ablageziels fort, um das in der Sitzung initiierte Array von Ziehelementen zu behandeln.
Um Ihre nominierte Ansicht so anzupassen, dass sie Daten als Teil des Ablageziels akzeptiert und verwendet, müssen Sie die folgenden Schritte ausführen:
DropInteraction
.dropInteraction (_: canHandle :)
.dropInteraction (_: sessionDidUpdate :)
Protokollmethode, die angibt, ob Sie die Sitzung kopieren, verschieben, ablehnen oder abbrechen möchten.dropInteraction (_: performDrop :)
Protokollmethode.Genauso wie wir unsere Ansicht so konfiguriert haben, dass sie das Ziehen ermöglicht, werden wir unsere benannte Ansicht symmetrisch so konfigurieren, dass sie abgelegte Elemente von einer Ziehsitzung akzeptiert, indem Sie die UIDropinteractionDelegate
und Umsetzung seiner DropInteraction
Delegatmethode:
let dropInteraction = UIDropInteraction (Delegat: dropInteractionDelegate) view.addInteraction (dropInteraction)
Um festzulegen, ob eine Ansicht Drag-Elemente akzeptieren kann oder ablehnt, implementieren wir das dropInteraction (_: canHandle :)
Protokollmethode. Mit der folgenden Methode können wir dem System mitteilen, ob es die Elemente annehmen kann, indem es den Typ der Objekte angibt, die es empfangen kann - in diesem Fall UIImages.
func dropInteraction (_action: UIDropInteraction, canHandle Sitzung: UIDropSession) -> Bool // Geben Sie den zulässigen Drop-Elementtyp explizit hier an. return session.canLoadObjects (ofClass: UIImage.self)
Wenn das Ansichtsobjekt keine Drop-Interaktionen akzeptiert, sollten Sie false von dieser Methode zurückgeben.
Binden Sie anschließend einen Drop-Vorschlag, um Daten aus der Drop-Sitzung zu akzeptieren. Obwohl dies eine optionale Methode ist, wird dringend empfohlen, diese Methode zu implementieren, da sie visuelle Hinweise darauf gibt, ob das Ablegen dazu führt, dass das Element kopiert oder verschoben wird oder ob das Ablegen insgesamt abgelehnt wird. Durch die Implementierung der dropInteraction (_: sessionDidUpdate :)
Protokollmethode, die a zurückgibt UIDropProposal
, Sie geben die Vorschlagsart anhand der spezifischen Aufzählungstypen an (UIDropOperation
). Die gültigen Typen, die Sie zurückgeben könnten, sind:
stornieren
verboten
Kopieren
Bewegung
func dropInteraction (_action: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal // Signalisieren Sie dem System, dass Sie das Element aus der Quell-App verschieben möchten (Sie können auch angeben, dass kopiert wird, statt zu verschieben). UIDropProposal ( Operation: .move)
Um den Inhalt des Datenelements in Ihrem Zielspeicherort zu verbrauchen, implementieren Sie das dropInteraction (_: performDrop :)
Protokollmethode in der Hintergrundwarteschlange (anstatt in der Hauptwarteschlange - dies gewährleistet die Reaktionsfähigkeit). Dies ist unten dargestellt:
func dropInteraction (_action: UIDropInteraction, performDrop-Sitzung: UIDropSession) // UIImage-Ziehelemente verwenden session.loadObjects (ofClass: UIImage.self) Elemente in let images = Elemente als! [UIImage] self.imageView.image = images.first
Wir haben gezeigt, wie Sie Drag & Drop in einer benutzerdefinierten Ansicht implementieren können. Gehen wir nun zum praktischen Teil dieses Lernprogramms über und implementieren Sie Drag & Drop in einer App mit einer Tabellenansicht.
Bisher haben wir darüber gesprochen, wie Sie Drag & Drop in benutzerdefinierten Ansichten implementieren können. Apple hat es jedoch auch leicht gemacht, Tabellen- und Auflistungsansichten durch Ziehen und Ablegen zu erweitern. Während Textfelder und Ansichten automatisch das Ziehen und Ablegen aus der Box unterstützen, werden in Tabellen- und Auflistungsansichten bestimmte Methoden, Delegaten und Eigenschaften angezeigt, mit denen das Drag & Drop-Verhalten angepasst werden kann. Wir werden uns das in Kürze ansehen.
Erstellen Sie zunächst ein neues Projekt in Xcode 9 und stellen Sie sicher, dass Sie auswählen Master-Detail-App aus dem Vorlagenfenster:
Bevor Sie mit den restlichen Schritten beginnen, bauen Sie das Projekt auf, lassen Sie es laufen und spielen Sie ein bisschen mit ihm. Sie werden sehen, dass ein neues Zeitstempeldatum erzeugt wird, wenn Sie das Plus auswählen (+) Taste. Wir werden diese App verbessern, indem der Benutzer die Zeitstempel ziehen und ordnen kann.
Drag & Drop wird in Tabellensichten (und Sammlungen) durch spezielle APIs unterstützt, die das Ziehen und Ablegen von Zeilen ermöglichen, indem unsere Tabellensicht so angepasst wird, dass beide übernommen werden UITableViewDragDelegate
und UITableViewDropDelegate
Protokolle. Öffne die MasterViewController.swift Datei und fügen Sie das folgende hinzu viewDidLoad ()
Methode:
func viewDidLoad () überschreiben super.viewDidLoad ()… self.tableView.dragDelegate = self self.tableView.dropDelegate = self…
Wie bei benutzerdefinierten Ansichten müssen wir die neue Ziehsitzung behandeln, wenn der Benutzer eine ausgewählte Zeile oder mehrere Zeilen / Auswahlen zieht. Wir machen das mit der Delegat-Methode tableView (_: itemsForBeginning: at :)
. Bei dieser Methode geben Sie entweder ein gefülltes Array zurück, das mit dem Ziehen der ausgewählten Zeilen beginnt, oder ein leeres Array, um zu verhindern, dass der Benutzer Inhalt aus diesem bestimmten Indexpfad zieht.
Fügen Sie die folgende Methode zu Ihrem hinzu MasterViewController.swift Datei:
func tableView (_ tableView: UITableView, itemsForBeginning-Sitzung: UIDragSession, bei indexPath: IndexPath) -> [UIDragItem] let dateItem = self.objects [indexPath.row] as! Zeichenfolge let data = dateItem.data (using: .utf8) let itemProvider = NSItemProvider () itemProvider.registerDataRepresentation (forTypeIdentifier: kUTTypePlainText als String, Sichtbarkeit: .all) Abschluss in Vervollständigung (data, nil) Rückgabe nil return [UIDragItem ( itemProvider: itemProvider)]
Ein Teil des hinzugefügten Codes sollte Ihnen bereits aus dem vorherigen Abschnitt bekannt sein. Im Wesentlichen erstellen wir jedoch ein Datenelement aus dem ausgewählten Objekt, umschließen es in einem NSItemProvider
, und geben Sie es in ein DragItem
.
Fahren Sie mit dem Aktivieren der Drop-Sitzung fort und fügen Sie die folgenden beiden Methoden hinzu:
func tableView (_ tableView: UITableView, canHandle-Sitzung: UIDropSession) -> Bool return session.canLoadObjects (ofClass: NSString.b) (): func tableView (_ tableView: UITableView, dropSessionDidUpdate) UITableViewDropProposal if tableView.hasActiveDrag if session.items.count> 1 return UITableViewDropProposal (Vorgang: .cancel) else return UITableViewDropProposal (Vorgang: .move, intent: .insertAtDestinationIndexPath) else return UITableAdapterProposal) Kopie, Absicht: .insertAtDestinationIndexPath)
Die erste Methode teilt dem System mit, dass es String-Datentypen als Teil seiner Drop-Sitzung verarbeiten kann. Die zweite Delegatmethode, tableView (_: dropSessionDidUpdate: withDestinationIndexPath :)
, verfolgt den potenziellen Ablageort und benachrichtigt die Methode bei jeder Änderung. Es zeigt auch visuelles Feedback an, um den Benutzer mithilfe eines kleinen visuellen Symbols darauf hinzuweisen, ob ein bestimmter Ort verboten oder akzeptabel ist.
Zuletzt behandeln wir das Ablegen und konsumieren das Datenelement, indem wir es aufrufen tableView (_: performDropWith :)
, Abrufen der gezogenen Datenelementzeile, Aktualisieren der Datenquelle unserer Tabellensicht und Einfügen der erforderlichen Zeilen in die Tabelle.
func tableView (_ tableView: UITableView, performDropWith-Koordinator: UITableViewDropCoordinator) let destinationIndexPath: IndexPath, wenn let indexPath = coordinator.destinationIndexPath destinationIndexPath = indexPath else // Liefert den letzten Indexpfad der Tabellenansicht. let section = tableView.numberOfSections - 1 let row = tableView.numberOfRows (inSection: section) destinationIndexPath = IndexPath (row: row, section: section) coordinator.session.loadObjects (ofClass: NSString.self) Elemente in // Consume Elemente ziehen let stringItems = items as! [String] var indexPaths = [IndexPath] () für (Index, Element) in stringItems.enumerated () let indexPath = IndexPath (Zeile: destinationIndexPath.row + index, Abschnitt: destinationIndexPath.section) self.objects.insert (item , at: indexPath.row) indexPaths.append (indexPath) tableView.insertRows (at: indexPaths, mit: .automatic)
Weitere Informationen zur Unterstützung von Drag & Drop in Ihren Tabellenansichten finden Sie in der eigenen Entwicklerdokumentation von Apple zum Thema "Drag & Drop-Unterstützung in Tabellenansichten".
Die von uns behandelten Inhalte sollten Ihnen bei der Implementierung von Drag & Drop in Ihren Apps helfen, sodass Benutzer visuell und interaktiv durch Inhalte innerhalb der vorhandenen Apps sowie zwischen Apps navigieren können.
Neben dem technischen Wissen über die Implementierung von Drag & Drop müssen Sie sich jedoch unbedingt die Zeit nehmen, um zu überlegen, wie Sie Drag & Drop implementieren sollten. Befolgen Sie dabei die von Apple in seinen Human Interface Guidelines (HIG) empfohlenen Best Practices Um den Benutzern die bestmögliche Benutzererfahrung für iOS 11 zu bieten.
Zum Abschluss werden wir einige der wichtigsten Aspekte ansprechen, angefangen mit visuellen Hinweisen. Laut HIG besteht die grundlegende Erfahrung mit Drag & Drop darin, dass visuelle Hinweise, wenn ein Benutzer mit bestimmten Inhalten interagiert, dem Benutzer eine aktive Drag-Sitzung anzeigen, die durch das Aufsteigen des Inhaltselements gekennzeichnet wird, zusammen mit einem Abzeichen, das anzeigt, wann gelöscht wird oder ist nicht möglich.
Wir haben dieses bewährte Verfahren bereits in unseren früheren Beispielen angewendet, als wir die tableView (_: dropSessionDidUpdate: withDestinationIndexPath :)
Methode, die angibt, ob das Ablageziel ein Verschieben, Kopieren oder Verbot ist. Sie sollten mit benutzerdefinierten Ansichten und Interaktionen sicherstellen, dass Sie die erwarteten Verhaltensweisen beibehalten, die von anderen iOS 11-Apps, insbesondere von System-Apps, unterstützt werden.
Ein weiterer wichtiger Aspekt, den Sie berücksichtigen sollten, ist die Entscheidung, ob Ihre Drag-Sitzung zu einem Verschieben oder Kopieren führt. Als Faustregel gilt, dass Apple beim Arbeiten mit derselben App im Allgemeinen zu einer Verschiebung führen sollte. Das Kopieren von Datenelementen ist jedoch sinnvoller, wenn Sie zwischen verschiedenen Apps ziehen. Zwar gibt es natürlich Ausnahmen, das Prinzip liegt jedoch darin, dass es für den Benutzer sinnvoll ist und was er erwartet.
Sie sollten auch in Bezug auf Quellen und Ziele denken und ob es sinnvoll ist, etwas zu ziehen oder nicht.
Werfen wir einen Blick auf einige Apple-eigene Dienstprogramme. In Notes können Sie z. B. Textinhalt auswählen und an andere Orte innerhalb der App oder auf andere Apps auf dem iPad über den geteilten Bildschirm ziehen. Mit der Erinnerungs-App können Sie Erinnerungselemente von einer Liste in eine andere verschieben. Denken Sie in Bezug auf die Funktionalität, wenn Sie entscheiden, wie Benutzer Ihre Inhalte verwenden.
Apples Leitfaden besagt, dass alle Inhalte, die bearbeitet werden können, die Annahme von abgelegten Inhalten unterstützen sollten, und dass alle Inhalte, die ausgewählt werden können, Drag-In-Inhalte sowie das Kopieren und Einfügen dieser Elementtypen unterstützen. Durch die Nutzung von Standardsystem-Textansichten und Textfeldern erhalten Sie Unterstützung für Drag & Drop aus der Box.
Sie sollten auch Drag & Drop für mehrere Elemente unterstützen, anstatt nur einzelne Elemente zu unterstützen. Benutzer können mehrere Finger gleichzeitig verwenden, um mehrere Elemente gleichzeitig auszuwählen und die ausgewählten Elemente in einer Gruppe zu stapeln, um sie an den beabsichtigten Zielen abzulegen. Ein Beispiel dafür ist das Auswählen mehrerer Bilder in der Fotos-App oder mehrerer Dateien in der Dateien-App.
Eine abschließende Richtlinie besteht darin, Benutzern die Möglichkeit zu geben, eine Aktion rückgängig zu machen oder einen Drop rückgängig zu machen. Benutzer sind seit langem an das Konzept des Rückgängigmachens einer Aktion in den meisten populären Apps gewöhnt. Drag & Drop sollte dabei keine Ausnahme darstellen. Benutzer sollten die Gewissheit haben, Drag & Drop einleiten zu können und diese Aktion rückgängig machen zu können, wenn das Element am falschen Ziel abgelegt wird.
Über das, was wir uns angeschaut haben, gibt es viele weitere Best-Practice-Richtlinien für Drag & Drop, z. B. Unterstützung für abgelegte visuelle Indikatoren, Anzeige fehlgeschlagener abgelaufener Aktionen und Fortschrittsindikatoren für nicht sofortige Drag-Sitzungen, z. B. Datenübertragungen. Eine vollständige Liste der bewährten Vorgehensweisen finden Sie in den iOS-Richtlinien für Benutzeroberflächen zu Drag & Drop.
In diesem Lernprogramm haben Sie erfahren, wie Sie Ihre iOS-Apps mit freundlicher Genehmigung von iOS 11 mit Drag & Drop anreichern können. Dabei haben wir untersucht, wie Sie sowohl benutzerdefinierte Ansichten als auch Tabellensichten als Ziehquellen und Ablageziele aktivieren können.
Als Teil der iOS-Entwicklung hin zu einer stärker gestengesteuerten Benutzeroberfläche wird Drag-and-Drop zweifellos schnell zu einer erwarteten Funktion für Benutzer im gesamten System. Daher sollten auch alle Apps von Drittanbietern konform sein. Genauso wichtig wie das Implementieren von Drag & Drop müssen Sie es richtig implementieren, so dass es für die Benutzer zur zweiten Natur wird, die Einfachheit und Funktionalität umfasst.
Und während Sie hier sind, lesen Sie einige unserer anderen Beiträge zur iOS-App-Entwicklung!