From 74cd37dd7c3c762ab4803965e7385343424ac379 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 18 Jan 2018 13:14:36 -0500 Subject: [PATCH] Clean up ahead of PR. --- Signal.xcodeproj/project.pbxproj | 6 +++++ .../ShareViewController.swift | 18 +++++-------- .../SignalShareExtension-Bridging-Header.h | 1 + .../utils/NSItemProvider+OWS.h | 26 +++++++++++++++++++ .../utils/NSItemProvider+OWS.m | 24 +++++++++++++++++ 5 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 SignalShareExtension/utils/NSItemProvider+OWS.h create mode 100644 SignalShareExtension/utils/NSItemProvider+OWS.m diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index b13eb6afe..c6f2749e1 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 2AE2882E4C2B96BFFF9EE27C /* Pods_SignalShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */; }; 340B02BA1FA0D6C700F9CFEC /* ConversationViewItemTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */; }; 340CB2271EAC25820001CAA1 /* UpdateGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340CB2261EAC25820001CAA1 /* UpdateGroupViewController.m */; }; + 341F1BEE20111A5300111571 /* NSItemProvider+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F1BEC20111A5200111571 /* NSItemProvider+OWS.m */; }; 341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */; }; 3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3430FE171F7751D4000EC51B /* GiphyAPI.swift */; }; 34330A5A1E7875FB00DF2FB9 /* fontawesome-webfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A591E7875FB00DF2FB9 /* fontawesome-webfont.ttf */; }; @@ -482,6 +483,8 @@ 340CB2251EAC25820001CAA1 /* UpdateGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateGroupViewController.h; sourceTree = ""; }; 340CB2261EAC25820001CAA1 /* UpdateGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UpdateGroupViewController.m; sourceTree = ""; }; 341458471FBE11C4005ABCF9 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = translations/fa.lproj/Localizable.strings; sourceTree = ""; }; + 341F1BEC20111A5200111571 /* NSItemProvider+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSItemProvider+OWS.m"; sourceTree = ""; }; + 341F1BED20111A5300111571 /* NSItemProvider+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSItemProvider+OWS.h"; sourceTree = ""; }; 341F2C0D1F2B8AE700D07D6B /* DebugUIMisc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIMisc.h; sourceTree = ""; }; 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIMisc.m; sourceTree = ""; }; 3430FE171F7751D4000EC51B /* GiphyAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GiphyAPI.swift; sourceTree = ""; }; @@ -1093,6 +1096,8 @@ 34480B2F1FD0921000BC14EF /* utils */ = { isa = PBXGroup; children = ( + 341F1BED20111A5300111571 /* NSItemProvider+OWS.h */, + 341F1BEC20111A5200111571 /* NSItemProvider+OWS.m */, 34480B341FD0929200BC14EF /* ShareAppExtensionContext.h */, 34480B351FD0929200BC14EF /* ShareAppExtensionContext.m */, ); @@ -2751,6 +2756,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 341F1BEE20111A5300111571 /* NSItemProvider+OWS.m in Sources */, 4535186B1FC635DD00210559 /* ShareViewController.swift in Sources */, 34480B361FD0929200BC14EF /* ShareAppExtensionContext.m in Sources */, 3461284B1FD0B94000532771 /* SAELoadViewController.swift in Sources */, diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index c373d59a4..48eaea8ba 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -609,23 +609,17 @@ public class ShareViewController: UINavigationController, ShareViewDelegate, SAE fulfill((url, srcUtiType)) } } else { + // It's unavoidable that we may sometimes receives data types that we + // don't know how to handle. + // + // See comments on NSItemProvider+OWS.h. let unexpectedTypeError = ShareViewControllerError.assertionError(description: "unexpected value: \(String(describing: value))") reject(unexpectedTypeError) } } - // NSItemProvider.loadItem(forTypeIdentifier:...) is unsafe to call from Swift, - // since it can yield values of arbitrary type. It has a highly unusual design - // in which its behavior depends on the _type_ of the completion handler. - // loadItem(forTypeIdentifier:...) tries to satisfy the expected type of the - // completion handler. This "hinting" only works in Objective-C. In Swift, - // The type of the completion handler must agree with the param type. - // - // Unfortunately, we have no alternative. Therefore, we face the real possibility - // of receiving an "unexpected type" that we don't know how to handle. - // - // See: https://developer.apple.com/documentation/foundation/nsitemprovider/1403900-loaditemfortypeidentifier - itemProvider.loadItem(forTypeIdentifier: srcUtiType, options: nil, completionHandler: loadCompletion) + // See comments on NSItemProvider+OWS.h. + itemProvider.loadData(forTypeIdentifier: srcUtiType, options: nil, completionHandler: loadCompletion) return promise.then { (itemUrl: URL, utiType: String) -> Promise in diff --git a/SignalShareExtension/SignalShareExtension-Bridging-Header.h b/SignalShareExtension/SignalShareExtension-Bridging-Header.h index 092490e40..b8d303e4e 100644 --- a/SignalShareExtension/SignalShareExtension-Bridging-Header.h +++ b/SignalShareExtension/SignalShareExtension-Bridging-Header.h @@ -6,6 +6,7 @@ #import // Separate iOS Frameworks from other imports. +#import "NSItemProvider+OWS.h" #import "ShareAppExtensionContext.h" #import #import diff --git a/SignalShareExtension/utils/NSItemProvider+OWS.h b/SignalShareExtension/utils/NSItemProvider+OWS.h new file mode 100644 index 000000000..d026fde35 --- /dev/null +++ b/SignalShareExtension/utils/NSItemProvider+OWS.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +NS_ASSUME_NONNULL_BEGIN + +@interface NSItemProvider (OWS) + +// NSItemProvider.loadItem(forTypeIdentifier:...) is unsafe to call from Swift, +// since it can yield values of arbitrary type. It has a highly unusual design +// in which its behavior depends on the _type_ of the completion handler. +// loadItem(forTypeIdentifier:...) tries to satisfy the expected type of the +// completion handler. This "hinting" only works in Objective-C. In Swift, +// The type of the completion handler must agree with the param type. +// +// Therefore we use an Objective-C category to hint to NSItemProvider that we +// prefer an instance of NSData. +// +// See: https://developer.apple.com/documentation/foundation/nsitemprovider/1403900-loaditemfortypeidentifier +- (void)loadDataForTypeIdentifier:(NSString *)typeIdentifier + options:(nullable NSDictionary *)options + completionHandler:(nullable NSItemProviderCompletionHandler)completionHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalShareExtension/utils/NSItemProvider+OWS.m b/SignalShareExtension/utils/NSItemProvider+OWS.m new file mode 100644 index 000000000..2d6e3478a --- /dev/null +++ b/SignalShareExtension/utils/NSItemProvider+OWS.m @@ -0,0 +1,24 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "NSItemProvider+OWS.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation NSItemProvider (OWS) + +- (void)loadDataForTypeIdentifier:(NSString *)typeIdentifier + options:(nullable NSDictionary *)options + completionHandler:(nullable NSItemProviderCompletionHandler)completionHandler +{ + [self loadItemForTypeIdentifier:typeIdentifier + options:options + completionHandler:^(NSData *_Nullable item, NSError *__null_unspecified error) { + completionHandler(item, error); + }]; +} + +@end + +NS_ASSUME_NONNULL_END