Как отправлять и получать пользовательские данные с AirDrop

Я боролся с этим целую вечность, так как не могу найти подробных примеров.

В моем приложении есть массив пользовательских данных, которые я хочу отправить другому пользователю с таким же приложением через AirDrop.

Первый шаг - отправка данных:

@IBAction func share_Button_Click(sender: UIBarButtonItem)
{
    let dataToShare: NSData = getMyCustomNSData()

    let controller = UIActivityViewController(activityItems: [dataToShare], applicationActivities: nil)
    controller.excludedActivityTypes = [UIActivityTypePostToFacebook, UIActivityTypePostToTwitter, UIActivityTypePostToWeibo, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypePostToFlickr, UIActivityTypePostToTencentWeibo, UIActivityTypeMail, UIActivityTypeAddToReadingList, UIActivityTypeOpenInIBooks, UIActivityTypeMessage]

    self.presentViewController(controller, animated: true, completion: nil)
}

Это преобразует мои данные в объект NSData, пользователь получает параметр общего доступа AirDrop, а данные отправляются на другой телефон. Все идет нормально...

Но как приложение другого пользователя узнает, как его получить?

Я читал о пользовательских типах UTI и объявил один, но, честно говоря, я не знаю, что добавить в объявление. И как вы указываете iOS, что данные, которые вы отправляете, соответствуют этому конкретному UTI?

Здесь и там есть примеры AirDrop, но они сосредоточены на том, чтобы делиться общими типами, такими как изображения, и ни один из тех, кого я обнаружил, не работал в деталях.

Кто-нибудь может помочь?

2 ответа

Решение

Пример кода AirDrop описывает, как определить свой собственный тип файла /UTI и использовать его для отправки пользовательских данных с помощью AirDrop.

Основные обязательные части:

  1. Информация о приложении

<...> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeName</key> <string>AirDrop Profile File Type</string> <key>LSHandlerRank</key> <string>Default</string> <key>LSItemContentTypes</key> <array> <string>com.apple.customProfileUTI.customprofile</string> </array> </dict> </array> <...>

  1. Для поддержки получения вашего пользовательского типа: в делегате приложения обработайте запуск с помощью fileURL, реализовав - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation, Убедитесь, что удалили / переместите файл для очистки в папке "Входящие".

  2. Для поддержки отправки одного пользовательского типа: элемент, который вы передаете UIActivityViewController, должен быть либо fileURL к файлу с расширением, зарегистрированным в качестве пользовательского типа файла, либо, если объект соответствует протоколу UIActivityItemSource и возвращает что-то типа NSData в - (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewControllerи ваш настоящий NSData BLOB в - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType, Затем в - (NSString *)activityViewController:(UIActivityViewController *)activityViewController dataTypeIdentifierForActivityType:(NSString *)activityType Вы хотите вернуть UTI вашего пользовательского типа, который вы зарегистрировали в info.plist.

Пример кода имеет прекрасный пример того, как сделать все это, а также как улучшить весь UX, добавив предварительно обрезанную фотографию соответствующего размера.

iOS13 (и выше)

Если метод делегата открытого URL-адреса в AppDelegate не вызывается

      func application(_ app: UIApplication, open url: URL, options [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { ...}

Вы должны использовать openURLContexts в SceneDelegate:

      func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else {return}    
}

Затем вы можете делать с «url» то, что вам нужно в вашем приложении.

Другие вопросы по тегам