共有ボタンがあるアプリがあります。私は、活動タイプに基づいて共有されるコンテンツをカスタマイズしたいと思います。たとえば、メッセージは画像とテキストを取得し、AirDropはファイルを取得します。このシナリオでは、UIActivityViewControllerが使用するアイテムをどのように変更できますか?
実際にこれは完全に機能しています。私が使用しているコードは、iOSのあらゆるバージョンでうまくいきました。しかし、私はどこにいなくてもどこにも戻っていないことを認識しました。それを修正する方法を見つけようとしています。
私は私の活動のビューコントローラをセットアップするには、このような何かを:
JUNActivityProvider *fileProvider = [[JUNActivityProvider alloc] initWithPlaceholderItem:[NSObject new]];
fileProvider.objectID = objectID;
fileProvider.fileURL = fileURL;
JUNActivityProvider *textProvider = [[JUNActivityProvider alloc] initWithPlaceholderItem:[NSString new]];
textProvider.objectID = objectID;
...
UIActivityViewController *activityController = [[UIActivityViewController alloc]
initWithActivityItems:@[fileProvider,imageProvider,textProvider,urlProvider,printFormatter]
applicationActivities:nil];
次にJUNActivityProvider
で、私はactivityType
に基づいて、戻り値をカスタマイズitem
方法があります。
- (id)item {
if (self.fileURL) {
if ([self.activityType isEqualToString:UIActivityTypeAirDrop]) {
// Create the file
return url;
}
} else if ([self.placeholderItem isKindOfClass:[UIImage class]]) {
if ([self.activityType isEqualToString:UIActivityTypeAirDrop] == NO &&
[self.activityType isEqualToString:UIActivityTypeMail] == NO &&
[self.activityType isEqualToString:UIActivityTypePrint] == NO) {
// Create the image
return image;
}
} else if ([self.placeholderItem isKindOfClass:[NSString class]]) {
if ([self.activityType isEqualToString:UIActivityTypeMail]) {
return @"example one";
} else if ([self.activityType isEqualToString:UIActivityTypeMessage] ||
[self.activityType isEqualToString:UIActivityTypeCopyToPasteboard]) {
return @"example two";
}
}
return nil;
}
を最後に返信return nil
が問題です。それはうまく動作し、私が欲しいものを正確に行います。書かれたドキュメントは値を返さなければならないと言っていませんが、ヘッダファイルは以下を行います:
- (nonnull id)item;
//ユーザがアクティビティを選択したときにセカンダリスレッドで呼び出されます。サブクラス化してnil以外の値を返す必要があります。
null以外の値が予想される場合は、nilを返すことでクラッシュする危険性がありません。この問題を解決する必要があります。私の唯一の選択肢は、UIActivityItemProvider
の使用をやめ、代わりにUIActivityItemSource
プロトコルを自分で実装することです。複数の項目があれば、項目の一つは、実際の値を返すように、単一のアクティビティのタイプに対して登録された場合
はnilである場合があります。そのプロトコルは明らかにあなたがゼロリターンができると述べている方法
activityViewController:itemForActivityType:
を含み、 。
パーフェクト。しかしここに問題があります:activityViewController:itemForActivityType:
がメインスレッドで呼び出され、特に私のアイテムの1つに問題を引き起こしています。ここには何が起こっているのかの概要があります:
- 私は非同期に実行するいくつかのメソッドを呼び出す必要があります。これを処理するために、ディスパッチセマフォを使用しようとしました。それは戻り値を設定する機会があるまでメソッドが返るのを防ぎます。
activityViewController:itemForActivityType:
がメインスレッドで呼び出されているので、そのスレッドが動作している間はロックされます。- UIViewをイメージに描画する必要があります。メインスレッドでその作業をしようとすると、セマフォーがタイムアウトするまで何も起こりません。しかし、私がメインスレッドでそれをしないと、クラッシュします。
私はこれに対処する方法がありません。基本的に私は準備が整うまでメソッドを返さないようにする必要がありますが、そこでいくつかの作業を行う必要があるため、メインスレッドをロックすることはできません。これは不可能だ...この仕事をする方法はありますか?
以前の試み(UIActivityItemProvider)から '[NSNull null]'を返してみましたか?これはオブジェクトであるという意味での "non-nil"戻り値ですが、ヌル/空の結果を示すためにCocoa APIでよく使用されています(UIActivityItemSourceを使用して他の場所で成功しました)。 – tgaul
@tgaul : '[NSNull null]'を使うと 'nonnull'を満たし、問題を引き起こすように見えませんが、超緊張してしまいます - それが何をしているのか分かりませんオブジェクトがありません。何年も何も目立った問題が起きていないという理由だけで、 'nil'を固執する方が少し気になります。 – robotspacer
' item'プロパティをnullableにすることを提案するバグレポートを提出しました:http: /www.openradar.me/radar?id=4563896690016256またはrdar:// 28394697 – robotspacer