2017-10-14 92 views
0

我试图从通讯录中选择联系人号码,而当我尝试为其更新逻辑时,它未能选择地址簿,而是当我单击号码时,它正在拨打这个号码。当我尝试选择号码时,代表团不会被呼叫。下面的代码虽然很长,但我试图描述一切(省略不相关的代码),所以你得到了这个问题的想法。联系人选取器的代表设置不正确

因此,复杂的事情是,我有一个HomeViewController,这一点我从一个叫HomeHelper(与UITableView的一个UIView)辅助设置中的所有数据。我确实从一个名为WidgetView的视图添加了一个UITableViewCell,并且正在设置的数据是从WidgetHelper。 WidgetHelper将加载一个名为WidgetProductAHelper(以及称为WidgetProductAView的视图)的UITableViewCell。

WidgetProductAView包含一个图像按钮,当我点击按钮时,它应该显示联系人选择器。我尝试将逻辑分离到一个名为AddressBookHelper的新类,这样我就可以在任何地方使用它,而不会有任何冗余。它成功显示地址簿,但是当我尝试单击其中一个时,它将重定向到详细联系人屏幕,而不是调用peoplePickerNavigationController的方法。我已为此设定了代表团,但仍然无效。

当我试图将它们写入一个类时,这些功能就会起作用。什么可能是错的?请帮忙弄清楚,我怀疑在使用助手时存在一些不适当的实现,但无法弄清楚。谢谢。

HomeViewController.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 
    } 

} 

HomeHelper.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) 
    } 

} 

WidgetHelper.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() 
} 

AddressBookHelper.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 
     //... 
    } 

} 

回答

2

看这个功能:

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... 

} 
+0

嗨@Michael Dautermann,非常感谢你,但它仍然不适合我。我已经更新了这个问题供您参考。 –

+0

你现在正在做的事情,''CNPicker'属性的每个调用返回一个'CNContactPickerViewController()',***在每次引用时创建一个新的CNContactPickerViewController。您需要创建一次CNContactPickerViewController,然后将其设置为一个属性,并且它会一直存在。 –

+0

oic,它现在正常工作,谢谢@Michael Dautermann :) –

0

CNContactPickerDelegate没有办法

func peoplePickerNavigationController(_ peoplePicker: ABPeoplePickerNavigationController, didSelectPerson person: ABRecord) { 
     // This method doesn't get called 
     //... 
} 

它代替

func contactPicker(CNContactPickerViewController, didSelect: CNContact) 
Called after a contact has been selected by the user. 

,你可以看到委托的方式完整列表在这里 https://developer.apple.com/documentation/contactsui/cncontactpickerdelegate

+0

嗨@Sergnsk,哎呀抱歉,我刚刚更新了代码,我从我的项目中复制了错误的代码,感谢您的注意;( –

相关问题