Как отправлять и получать пользовательские данные с 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.
Основные обязательные части:
- Информация о приложении
<...>
<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>
<...>
Для поддержки получения вашего пользовательского типа: в делегате приложения обработайте запуск с помощью fileURL, реализовав
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
, Убедитесь, что удалили / переместите файл для очистки в папке "Входящие".Для поддержки отправки одного пользовательского типа: элемент, который вы передаете 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» то, что вам нужно в вашем приложении.