2017-08-02 1 views
2

J'essaie d'intégrer la fonctionnalité de glisser iOS 11 glisser & dans une application, à partir de Xcode 9 bêta. Je suis intéressant sur la création d'un NSItemProvider qui peut être compris par l'application de calendrier standard. Mon glisser commence à partir d'un UITableView, donc une seule méthode dragDelegate implémentée.iOS 11 glisser et déposer: tomber sur l'application calendrier standard

Jusqu'à présent, j'ai essayé ce qui suit:

let text = "Rendez-vous at \(clientName)" 
    let data = text.data(using: .utf8) 

    let itemProvider = NSItemProvider() 
    itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypeCalendarEvent as String, visibility: .all) { completion in 
     completion(data, nil) 
     return nil 
    } 

    let dragItem = UIDragItem(itemProvider: itemProvider) 

Et aussi essayé en utilisant l'identifiant de type kUTTypePlainText. Pas de chance, l'application de calendrier ne enregistre pas la baisse.

Je ne trouve aucune documentation officielle à ce sujet. J'espère que l'application de calendrier recherche des données de calendrier standard, et cela ne se limite pas aux applications standard communiquant les unes avec les autres. Par exemple, vous pouvez faire glisser du texte à partir de l'application Notes et le déposer dans le calendrier pour créer un événement.

Quelqu'un sait ce que je pourrais essayer?

Merci d'avance.

Répondre

2

TL; DR: Les ingrédients secrets pour obtenir le défaut iOS application Calendrier de reconnaître votre objet personnalisé conforme au protocole NSItemProviderWriting sont l'identifiant de type "com.apple.ical.ics" et l'exportation de votre objet personnalisé en tant que chaîne iCalendar (vEvent). J'ai déjà joué avec ça pendant quelques jours et j'ai finalement réussi à le faire fonctionner! Je vais essayer de briser mes pas autant que possible.

  1. Création d'un objet personnalisé qui est conforme à NSItemProviderWriting:
    • Pour être conforme au protocole, vous aurez besoin de mettre en œuvre writableTypeIdentifiersForItemProvider et loadData(withTypeIdentifier:, forItemProviderCompletionHandler:).
    • Le tableau d'identifiants est une liste des identificateurs de type que vous pouvez exporter, dans l'ordre de fidélité, avec la plus haute fidélité en premier. Donc, mettez d'abord votre identifiant de type personnalisé et incluez "com.apple.ical.ics" après. La fonction loadData, mentionnée ci-dessus, tente de trouver un identifiant que la destination de glissement (l'application Calendrier de ce scénario) prend en charge et que votre application prend également en charge, en essayant d'obtenir la plus haute fidélité en premier.

Par exemple:

public static var writableTypeIdentifiersForItemProvider: [String] { 
    return ["com.yourcompany.myEvent", "com.apple.ical.ics"] 
} 

public func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? { 
    switch typeIdentifier { 
    case "com.yourcompany.myEvent": // Your custom handling goes here 
    case "com.apple.ical.ics": completionHandler(createVEvent(), nil) 
    default: completionHandler(nil, YourAppError.someCustomError) 
    } 

    return nil 
} 
  1. Créer une chaîne iCalendar vEvent avec vos informations d'événement personnalisé:
    • Cette étape est très similaire à la démo dans Session 227 de WWDC 2017, où ils créent une chaîne vCard pour un contact personnalisé. Checkout le projet de démonstration de cette session. Fondamentalement, l'application Calendar prend en charge quelques types spécifiques d'identifiants de type et le format iCal en fait partie.Par conséquent, vous avez juste besoin de créer une méthode d'assistance pour transformer votre type d'événement personnalisé en une chaîne iCalendar.
    • Je ne vais pas entrer dans les détails sur vEvent s mais il y a beaucoup de bonnes informations here et here.

Voici une suggestion:

private func createVEvent() -> Data? { 
    let today = Date() 

    let dateFormatter = DateFormatter() 
    dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'" 
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC") 

    let startDateString = dateFormatter.string(from: startDate) 
    let endDateString = dateFormatter.string(from: endDate) 
    let todayString = dateFormatter.string(from: today) 

    var vCalendarText = "BEGIN:VCALENDAR\n" 
    vCalendarText += "VERSION:2.0\n" 
    vCalendarText += "PRODID:-//Your Company//App Name//EN\n" 
    vCalendarText += "BEGIN:VEVENT\n" 

    vCalendarText += "UID:\(identifier.uuidString)\n" 
    vCalendarText += "SUMMARY:\(name)\n" 
    vCalendarText += "DTSTAMP:\(todayString)\n" 
    vCalendarText += "DTSTART:\(startDateString)\n" 
    vCalendarText += "DTEND:\(endDateString)\n" 

    vCalendarText += "END:VEVENT\n" 
    vCalendarText += "END:VCALENDAR" 

    return vCalendarText.data(using: .utf8) 
} 

↑ similaires à la fonction createVCard() de cette démonstration de la session mentionné plus tôt ...

Ca y est! C'est à peu près tout ce dont vous avez besoin. La partie la plus difficile est de savoir quel identificateur l'application Agenda prend en charge et comment créer un vEvent. Merci à quiker pour trouver les identifiants pris en charge.

Un dernier conseil: vous pouvez valider votre chaîne iCalendar avec this nifty tool here.

Notez que cela permet seulement de laisser tomber votre objet personnalisé. Faire glisser un événement du calendrier à votre application est une histoire différente, mais vous pouvez le comprendre à partir de mes conseils ici. :)

Bonne codification!

+0

Wow, quelle réponse géniale. Je vais tester cela aujourd'hui et revenir avec la validation. Merci beaucoup pour le temps que vous avez pris en donnant tous ces détails. –

+0

Hey Lucas, j'ai testé ton exemple, et ça marche super bien. Cependant, il y a une chose qui me dérange. Si je ne mets pas de valeur DTSTART, la chute échoue. Cependant si je mets une valeur DTSTART, la goutte réussit, mais ignore l'endroit dans le calendrier quand l'article est abandonné. Ce type de défait le but de laisser tomber l'élément visuellement à la date et l'heure que je veux créer l'événement. Une idée ? –