我试图从通讯簿中选择联系人号码,当我试图修改其逻辑时,它未能选择通讯簿,相反,当我单击该号码时,它正在调用该号码。当我试图选择号码时,代表团没有被调用。
下面的代码虽然很长,但是我试图描述所有的内容(省略不相关的代码),所以您可以理解这个问题。
所以,复杂的事情是,我有一个HomeViewController,我从一个名为HomeHelper的助手(一个带UITableView的UIView)中设置所有数据。我确实从一个名为WidgetView的视图添加了UITableViewCell,并且数据是从WidgetHelper设置的。WidgetHelper将加载名为WidgetProductAHelper的UITableViewCell(以及名为WidgetProductAView的视图)。
WidgetProductAView包含一个图像按钮,当我单击该按钮时,它应该会显示联系人选取器。我尝试将逻辑分离到一个名为AddressBookHelper的新类,这样我就可以在任何地方使用它,而无需任何冗余。它确实成功地显示了地址簿,但是当我尝试单击其中一个地址簿时,它将重定向到详细联系人屏幕,而不是调用peoplePickerNavigationController的方法。我已经安排了代表团,但仍然没有成功。
当我试着只在一节课上写的时候,这些东西确实有效。怎么了?请帮忙弄清楚,我怀疑在使用helpers上有一些不正确的实现,但无法弄清楚。谢谢。
homewiewcontroller.swift主页视图控制器

class HomeViewController: UIViewController {

    var dataSource : UITableViewDataSource?
    var delegate : UITableViewDelegate?

    override func viewDidLoad() {
        //
        let helper = HomeHelper()

        helper.homeViewController = self

        dataSource = helper
        delegate = helper

        tableView.dataSource = dataSource
        tableView.delegate = delegate
    }

}

家庭助手.swift
class HomeHelper: UITableViewDataSource, UITableViewDelegate, WidgetViewDelegate {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "WidgetView", for: indexPath) as? UITableViewCell else {
            return UITableViewCell()
        }

        if let customView = cell.customView as? WidgetView {
            let helper = WidgetHelper()
            customView.helperDataSource = helper
            customView.helperDelegate = helper
            customView.delegate = self
            helper.controller = customView

            customView.initCell()

            return cell
        }
    }

    // MARK: - WidgetViewDelegate

    func presentOnHome(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Swift.Void)? = nil) {
        self.homeViewController?.present(viewControllerToPresent, animated: animated, completion: completion)
    }

}

WidgetView.swift网站
protocol WidgetViewDelegate {
    func presentOnHome(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Swift.Void)?)
}

class WidgetView: NSObject {

    var delegate: WidgetViewDelegate?

    var helperDataSource: WidgetViewHelperDataSource?
    var helperDelegate: WidgetViewHelperDelegate?

    func initCell() {
        //
        tableView.dataSource = helperDataSource
        tableView.delegate = helperDelegate
    }

    func presentOnHome(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Swift.Void)?) {
        delegate?.presentOnHome(viewControllerToPresent, animated: animated, completion: completion)
    }

}

widgetshelper.swift网站
class WidgetHelper: UITableViewDataSource, UITableViewDelegate, WidgetProductAHelperDelegate {

    var controller: WidgetView?

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "WidgetProductAView", for: indexPath) as? UITableViewCell else {
            return UITableViewCell()
        }

        if let customView = cell.customView as? WidgetProductAHelper {
            customView.parentHelper = self
            customView.delegate = self
            customView.initCell()

            return cell
        }
    }

    // MARK: - WidgetProductAHelperDelegate

    func presentOnHome(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Swift.Void)? = nil) {
        self.homeViewController?.present(viewControllerToPresent, animated: animated, completion: completion)
    }

}

WidgetProductAHelper.swift公司
protocol WidgetProductAHelperDelegate {
    func presentOnHome(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Swift.Void)?)
}

class WidgetProductAHelper: UITableViewDataSource, UITableViewDelegate {

    @IBOutlet var contactImageButton: UIButton!

    var parentHelper: WidgetHelper?
    var delegate: WidgetProductAHelperDelegate?

}

func initCell() {
    //
    contactImageButton.isUserInteractionEnabled = true;
    contactImageButton.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(WidgetProductAHelper.contactImageButtonTapped(_:))))
}

func contactImageButtonTapped(_ sender: UIGestureRecognizer) {
    let addressBookHelper = AddressBookHelper()
    addressBookHelper.contactImageButton = contactImageButton
    addressBookHelper.completion = { (result) in
        switch result {
        case .presentOnHome(let viewControllerToPresent) :
            self.parentHelper?.presentOnHome(viewControllerToPresent, animated: true, completion: nil)

            break
        }
    }
    addressBookHelper.addressBookButtonTapped()
}

地址bookhelper.swift
正如您在下面的代码中看到的,我已经将CNPicker的委托设置为类,但是没有调用委托的方法。对于displayErrorMessage()和displayPromptForAddressBookRequestAccess()等其他内容,它在显示弹出窗口时效果很好。
enum AddressBookActionResult {
    case presentOnHome(viewControllerToPresent: UIViewController)
}

class AddressBookHelper: NSObject, CNContactPickerDelegate {

    var completion: ((AddressBookActionResult) -> ())?

    var contactImageButton: UIButton?

    @available(iOS 9.0, *)
    var CNPicker: CNContactPickerViewController {
        return CNContactPickerViewController()
    }

    func addressBookButtonTapped() {
        switch CNContactStore.authorizationStatus(for: .contacts) {
        case .denied, .restricted:
            // displayErrorMessage()
            break
        case .authorized:
            openUserAddressBook()
            break
        case .notDetermined:
            // displayPromptForAddressBookRequestAccess()
            break
        }
    }

    func openUserAddressBook() {
        if #available(iOS 9.0, *) {
            CNPicker.delegate = self
            completion?(.presentOnHome(viewControllerToPresent: CNPicker))
        }
    }


    // MARK: - CNContactPickerDelegate

    @available(iOS 9.0, *)
    func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
        // This method doesn't get called
        //...
    }

}

最佳答案

看看这个函数:

func openUserAddressBook() {
        let CNPicker: CNContactPickerViewController = CNContactPickerViewController()
        CNPicker.delegate = self
        completion?(.presentOnHome(viewControllerToPresent: CNPicker))
    }

您在该函数中创建了CNPicker,并且一旦退出openUserAddressBook函数,CNPicker就会被释放。
最好将CNPicker设置为位于AddressBookHelper顶部的属性。
例如。:
class AddressBookHelper: NSObject, CNContactPickerDelegate {

    // create CNContactPickerViewController once and only once
    let cnPicker = CNContactPickerViewController()

    var completion: ((AddressBookActionResult) -> ())?

    override init()
    {
        super.init()

        // and set the delegate of the picker to this Helper class
        self.cnPicker.delegate = self
    }

    func openUserAddressBook() {
        completion?(.presentOnHome(viewControllerToPresent: self.cnPicker))
    }

    func contactPicker(_ picker: CNContactPickerViewController,
                   didSelect contact: CNContact)
    {
        print("selected a contact!")
    }

    // and other delegate methods can be implemented and they
    // will be called...

}

关于ios - 联系人选择器的委派设置不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46744278/

10-12 12:47
查看更多