29

[iOS 10 で修正されたようです!]ということで、以下は iOS 9 のみに適用されます...


私は Apple の新しい Contacts フレームワークを試していて、CNContactViewController の 3 つの形式の 1 つに大きなバグがあることを発見しました。アプリが役に立たなくなるように、周囲のインターフェースを破壊します。ユーザーは立ち往生しています。

このバグを簡単に確認できるように、サンプル プロジェクトをhttps://github.com/mattneub/CNContactViewControllerBugに投稿しました。

実験するには、プロジェクトを実行し、次の手順を実行します。

  1. ボタン(不明な人物)をタップします。

  2. 要求された場合はアクセスを許可します。

  3. ナビゲーション インターフェイスに部分的な連絡先が表示されます (上部の [戻る] ボタンに注意してください)。

  4. [既存の連絡先に追加] をタップします。連絡先ピッカーが表示されます。

  5. [キャンセル] をタップします。ここから何をするかは問題ではありませんが、[キャンセル] をタップするのが最も簡単で、バグに到達する最速の方法です。

  6. 部分的な接触に戻りましたが、ナビゲーション インターフェイスはなくなりました。ユーザーは、このインターフェイスから逃れる方法がありません。アプリはホースです。

明確にするために、実行する必要がある手順のスクリーンショットを次に示します。

ここに画像の説明を入力

これを表示するには、[既存の連絡先に追加] をタップします。

ここに画像の説明を入力

これを表示するには、[キャンセル] をタップします。最初のスクリーン ショットと同じですが、ナビゲーション バーがなくなっていることに注意してください。

ここに画像の説明を入力

このバグを回避するために多くの方法を試しましたが、方法がないようです。私が知る限り、このウィンドウは「プロセス外」のフレームワークによって表示されており、アプリの一部ではありません。あなたはそれを取り除くことはできません。

それで、質問は何ですか?私はこれだと思います: 誰でもこのView Controllerを(この形式で)使用可能にする方法を教えてもらえますか? 私が見つけていない回避策はありますか?

編集このバグは iOS 9.0 で発生し、iOS 9.1 にも存在します。コメントで、@SergeySkopus は、非推奨の Address Book フレームワークに切り替えても役に立たないと報告しています。バグは基になる構造のどこかにあります。

4

7 に答える 7

7

明らかにこれはバグです。Apple が最終的に私のバグ レポートに重複していると宣言したからです。

于 2015-11-17T16:31:43.780 に答える
5

「CNContactViewController forUnknownContact」を使用可能にする唯一の方法は、ナビゲーションバーを放棄し、ツールバーを使用してモーダル ビューを終了することです (Objective C の場合)。

CNContactViewController *picker = [CNContactViewController viewControllerForUnknownContact: newContact];
picker.delegate = self;

UINavigationController *newNavigationController = [[UINavigationController alloc] initWithRootViewController:picker];

UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStyleDone target:self action:@selector(YourDismissFunction)];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[picker setToolbarItems:[[NSArray alloc] initWithObjects:flexibleSpace, doneButton, flexibleSpace, nil] animated:NO];

newNavigationController.toolbarHidden = NO;
picker.edgesForExtendedLayout = UIRectEdgeNone;

[self presentViewController:newNavigationController animated:YES completion:nil];

それが役立つことを願って

于 2016-01-17T22:41:07.463 に答える
0

これは、私が一人ではないことがわかってうれしかった問題の 1 つです。

CNContactViewController(contact:) を使用して連絡先を表示すると、同じ問題が発生します。

画像または「共有連絡先」がタップされると、ルート CNContactViewController のナビゲーション バーが消え、ユーザーが動けなくなりました。これは、iOS 9.3.3 の時点では修正されていません。

この時点での解決策は、uitoolbar を使用することです。問題は、連絡先の画像データが全画面表示されている場合でも、これが常に下部に表示されることです。

// initialise new contact view controller to display with contact
                let contactVC = CNContactViewController(forContact: contact!)

                // set view controller delegate
                contactVC.delegate = self

                // set view controller contact store
                contactVC.contactStore = self.store

                // enable actions
                contactVC.allowsActions = true

                // disable editing
                contactVC.allowsEditing = false

                // add cancel button
                let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: #selector(dismissContactVC(_:)))

                // add flexible space
                let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)

                // add to toolbar
                contactVC.setToolbarItems([flexibleSpace, cancelButton, flexibleSpace], animated: false)

                // contact view controller must be embedded in navigation controller
                // initialise navigation controller with contact view controller as root
                let navigationVC = SubClassNavigationController(rootViewController: contactVC)

                // show toolbar
                navigationVC.setToolbarHidden(false, animated: false)

                // set navigation presentation style
                navigationVC.modalPresentationStyle = UIModalPresentationStyle.CurrentContext

                // present view controller
                self.presentViewController(navigationVC, animated: true, completion: nil)

この後、最初に cncontactviewcontroller を提示すると空白のナビゲーション バーが表示されるので、これを削除するために uinavigationcontroller をサブクラス化し、viewWillAppear(animated:) で関数 setnavigationbar(hidden:animated:) を呼び出してナビゲーション バーを非表示にします。

これは理想的な解決策とは言えないため、Apple がこれをすぐに修正してくれることを願っています。

于 2016-07-29T12:22:17.520 に答える
-1

さて、問題を一時的に解決する3つの方法を見つけました。

スウィフト 2.2 バージョン:


オプション 1: デバイスをシェイクしてナビゲーション バーを表示するか、直接閉じる

class CustomContactViewController: CNContactViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        UIApplication.sharedApplication().applicationSupportsShakeToEdit = true
    }

    override func canBecomeFirstResponder() -> Bool {
        return true
    }        

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)            
        becomeFirstResponder()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)            
        resignFirstResponder()
        UIApplication.sharedApplication().applicationSupportsShakeToEdit = false
    }

    override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
        navigationController?.setNavigationBarHidden(false, animated: true)

        // or just dismiss
        // dismissViewControllerAnimated(true, completion: nil)

        // or pop
        // navigationController?.popViewControllerAnimated(true)

    }
}


オプション 2: タイマーを設定して、ナビゲーション バーを強制的に表示します。しかし... また、新しい問題が発生します。連絡先のアバターを編集または共有することはできません。

class CustomContactViewController: CNContactViewController {

    var timer: NSTimer?

    override func viewDidLoad() {
        super.viewDidLoad()
        timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(showNavigationBar), userInfo: nil, repeats: true)
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        timer?.fire()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        timer?.invalidate()
    }

    @objc private func showNavigationBar() {
        navigationController?.setNavigationBarHidden(false, animated: true)
    }
}


オプション 3: 一番上のビューに閉じるボタンを作成します。

class CustomContactViewController: CNContactViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        configureDismissButton()
    }

    private func configureDismissButton() {

        guard let topView = UIApplication.topMostViewController?.view else { return }

        let button = UIButton()
        button.setImage(UIImage(named: "close"), forState: .Normal)
        button.addTarget(self, action: #selector(dismissViewController), forControlEvents: .TouchUpInside)
        topView.addSubview(button)

        // just use SnapKit to set AutoLayout
        button.snp_makeConstraints { (make) in
            make.width.height.equalTo(36)
            make.bottom.equalTo(8)
            make.left.equalTo(-8)
        }
    }

    @objc private func dismissViewController() {
        dismissViewControllerAnimated(true, completion: nil)
    }

    var topMostViewController: UIViewController? {
        var topController = UIApplication.sharedApplication().keyWindow?.rootViewController
        while topController?.presentedViewController != nil {
            topController = topController?.presentedViewController
        }
        return topController
    }
}

ここに画像の説明を入力

于 2016-05-22T14:55:50.587 に答える