web-dev-qa-db-ja.com

iOS 13 UIActivityViewControllerは、前のVC画像の保存後に自動的に表示します

「画像をライブラリに保存」機能を実装してから現在のビューコントローラーに戻そうとしていますが、新しいiOS 13では現在のビューコントローラーを表示したビューコントローラーに戻ります。

PHPhotoLibrary.requestAuthorization({(_ status: PHAuthorizationStatus) -> Void in })

let shareItems: Array = [newImg,"Hello"] as [Any]

let activityController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)

if UIDevice.current.userInterfaceIdiom == .pad {
    activityController.popoverPresentationController?.sourceView = saveButton
}

present(activityController, animated: true)
20
Diana

@KDPのソリューションのSwiftバージョン:

let fakeViewController = TransparentViewController()
fakeViewController.modalPresentationStyle = .overFullScreen

activityViewController.completionWithItemsHandler = { [weak fakeViewController] _, _, _, _ in
    if let presentingViewController = fakeViewController?.presentingViewController {
        presentingViewController.dismiss(animated: false, completion: nil)
    } else {
        fakeViewController?.dismiss(animated: false, completion: nil)
    }
}
present(fakeViewController, animated: true) { [weak fakeViewController] in
    fakeViewController?.present(activityViewController, animated: true, completion: nil)
}

fakeViewControllerは、アクティビティの完了によって却下されるか、完了時に却下する必要があります。

5
janh

次のサルのパッチを生成しました(iOS 13.1.2で確認済み)

- (void)export {

  //
  // ... Generate Your Activity Items ...
  //

  UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems
                                                                                           applicationActivities:nil
                                                                                                   completeBlock:^(NSError *activityError, BOOL completed) {
                                                                                                       // Swizzling Dismiss Method
                                                                                                       [[self class]   switchInstanceMethodFrom:@selector(dismissViewControllerAnimated:completion:) To:@selector(lockedDismissViewControllerAnimated:completion:)];
                                                                                                   }
                                                                                ];
  // Swizzling Dismiss Method
  [[self class] switchInstanceMethodFrom:@selector(dismissViewControllerAnimated:completion:) To:@selector(lockedDismissViewControllerAnimated:completion:)];
  [self presentViewController:activityViewController animated:YES completion:nil];
}

- (void)lockedDismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
    if ([self presentedViewController]) {
        [self lockedDismissViewControllerAnimated:flag completion:completion];
    }
}

// from http://qiita.com/paming/items/25eaf89e4f448ab05752
+(void)switchInstanceMethodFrom:(SEL)from To:(SEL)to
{
    Method fromMethod = class_getInstanceMethod(self,from);
    Method toMethod   = class_getInstanceMethod(self,to  );
    method_exchangeImplementations(fromMethod, toMethod);
}
4
ANNotunzdY

ここでは、このバグを回避する方法を示します。フェイクビューコントローラーを作成し、現在のスタックにプッシュします。 UIActivityTypeSaveToCameraRollはスタックのトップビューコントローラーを閉じますが、他のオプションは閉じないようです。アクティビティタイプが完了しておらず、UIActivityTypeSaveToCameraRollの場合は、完了ブロックで偽のビューコントローラーを閉じるようにします。

typeof(self) __weak weakSelf = self;

[self.activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
        if (activityType== UIActivityTypeSaveToCameraRoll && completed){
              weakSelf.activityViewController = nil;
        }
        else{
             [weakSelf dismissViewControllerAnimated:NO completion:nil];
             weakSelf.activityViewController = nil;       
        }
}];


UIViewController *fakeVC=[[UIViewController alloc] init];

[self presentViewController:fakeVC animated:NO completion:^{
       [fakeVC presentViewController:self.activityViewController animated:YES completion:nil];
}];
2
KDP
- (UIWindow *)displayWindow
{
    if (!_displayWindow)
    {
        _displayWindow = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
        _displayWindow.rootViewController = [[UIViewController alloc] init];
    }
    return _displayWindow;
}

- (void)showActivityController
{
    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[] applicationActivities:nil];
    activityViewController.completionWithItemsHandler = ^(UIActivityType __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError)
    {
        [UIApplication.sharedApplication.delegate.window makeKeyAndVisible];
    };

    [self.displayWindow makeKeyAndVisible];
    [self.displayWindow.rootViewController presentViewController:activityViewController animated:true completion:nil];
}

_displayWindowは強い参照です。

1
franze

ルートビューコントローラーを現在のウィンドウに設定することでこの問題を解決しましたが、なぜ現在のビューコントローラーが閉じられるのかわかりません。 iOS 13で新しいビューコントローラーを表示しているときに、カードスタックアップスタイルに表示され、UIActivityControllerで[画像を保存]を選択すると、現在のビューコントローラー(カード)が非表示になり、前のビューコントローラーが表示されます。

0
Silverize