联系人选取器的代表设置不正确
我试图从通讯录中选择联系人号码,而当我尝试为其更新逻辑时,它未能选择地址簿,而是当我单击号码时,它正在拨打这个号码。当我尝试选择号码时,代表团不会被呼叫。下面的代码虽然很长,但我试图描述一切(省略不相关的代码),所以你得到了这个问题的想法。联系人选取器的代表设置不正确
因此,复杂的事情是,我有一个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
//...
}
}
看这个功能:
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...
}
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
嗨@Sergnsk,哎呀抱歉,我刚刚更新了代码,我从我的项目中复制了错误的代码,感谢您的注意;( –
嗨@Michael Dautermann,非常感谢你,但它仍然不适合我。我已经更新了这个问题供您参考。 –
你现在正在做的事情,''CNPicker'属性的每个调用返回一个'CNContactPickerViewController()',***在每次引用时创建一个新的CNContactPickerViewController。您需要创建一次CNContactPickerViewController,然后将其设置为一个属性,并且它会一直存在。 –
oic,它现在正常工作,谢谢@Michael Dautermann :) –