我正在尝试从地址簿中选择联系号码,当我尝试修改它的逻辑时,它无法选择地址簿,相反,当我点击该号码时,它会拨打该号码。在我尝试选择号码时,代表团不会被呼叫。
下面的代码很长,但我试图描述所有内容(省略不相关的代码),这样你就可以了解问题。
所以,复杂的事情是,我有一个 HomeViewController ,我从一个名为 HomeHelper 的帮助器(一个带有UITableView的UIView)中设置了所有数据。我从名为 WidgetView 的视图中添加了一个UITableViewCell,并且数据是从 WidgetHelper 设置的。 WidgetHelper将加载名为 WidgetProductAHelper 的UITableViewCell(以及名为WidgetProductAView的视图)。
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
//...
}
}
答案 0 :(得分:3)
看看这个功能:
func openUserAddressBook() {
let CNPicker: CNContactPickerViewController = CNContactPickerViewController()
CNPicker.delegate = self
completion?(.presentOnHome(viewControllerToPresent: CNPicker))
}
您正在该功能中创建CNPicker
,只要退出 openUserAddressBook
功能,CNPicker
就会被释放。
最好让CNPicker
属于AddressBookHelper顶部的属性。
e.g:
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...
}
答案 1 :(得分: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