通过自定义按钮执行Segue

时间:2018-11-24 21:13:25

标签: ios swift xcode

我创建了一个自定义按钮,以在按钮中包含我需要的信息:

class CustomButton: UIButton {   
   var urlString: String?
   var documentType: String?
   var requestEntity: String?
   var requestSortBy: [NSSortDescriptor]?
   var requestPredicate: NSPredicate?
}

当我在collectionView中创建单元格时(嵌入在tableView中),我将信息包含在名为documentTypeButton的自定义按钮中。也是执行功能HomeTableViewController.documentTypeButtonTapped(_:)以执行segue的目标。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let languageSelected = UserDefaults().value(forKey: "language") as! String

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell

    cell.documentTypeButton.documentType = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].name
    cell.documentTypeButton.requestEntity = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].entityName
    cell.documentTypeButton.requestSortBy = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].sortBy
    cell.documentTypeButton.requestPredicate = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].predicate
    cell.documentTypeButton.addTarget(nil, action: #selector(HomeTableViewController.documentTypeButtonTapped(_:)), for: .touchUpInside)


    return cell

}

HomeTableViewController中,我具有在触摸按钮内部时要执行的功能:

@objc func documentTypeButtonTapped(_ sender: CustomButton) {

    performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
    print(sender.documentType)
    print(sender.requestEntity)

}

func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

    let languageSelected = UserDefaults().value(forKey: "language") as! String

    if let destination = segue.destination as? DocumentListTableViewController {

        destination.titlePassed = sender.documentType!.localized(lang: languageSelected)
        destination.requestedEntity = sender.requestEntity
        destination.requestedSortBy = sender.requestSortBy
        destination.requestedPredicate = sender.requestPredicate

    }

}

上面的打印语句可以很好地工作并打印信息。然后segue转到DocumentListTableViewController

viewDidLoad的{​​{1}}中,添加了以下内容:

DocumentListTableViewController

两个打印语句将打印override func viewDidLoad() { super.viewDidLoad() print(titlePassed) print(requestedEntity) }

我想问题应该出在nil上,也许是发件人……我不知道。

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

尝试像这样在sender方法中传递performSegue()参数:

@objc func documentTypeButtonTapped(_ sender: CustomButton) {

    performSegue(withIdentifier: "goToDocumentList", sender: sender)
    print(sender.documentType)
    print(sender.requestEntity)

}

问题在于您正在实例化CustomButton()类型的新对象,而不是传递sender

答案 1 :(得分:2)

问题是您在CustomButton调用中传递了performSegue的新(空)实例,而不是在动作的sender中传递了

但是创建数据按钮作为数据容器的自定义按钮的设计仍然很糟糕。 不要这样做。太可怕了。

有一个更简单,更有效的解决方案:

AllDocumentsCollectionViewCell中创建回调闭包

var callback : (()->Void)?

和一个IBAction并将其连接到按钮,点击按钮时将调用回调。

@IBAction func documentTypeButtonTapped(_ sender: UIButton) {
    callback?()
}

HomeTableViewController中,为回调分配一个闭包,在其中执行segue并传递数据源数组的项。

但是在每次UserDefaults().value(的调用中调用collectionView并为索引路径获取 same 项4次的方式非常低效。并且永远不要使用value(forKeystring(forKey中有UserDefaults

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let languageSelected = UserDefaults().string(forKey: "language")! 

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
    cell.callback { [weak self] in
         let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
         self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
    }
    return cell

}

prepare(for中获取数据源项(我不知道它是什么类型),然后从那里检索信息。您甚至可以将整个项目传递给目标视图控制器。

func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

    let languageSelected = UserDefaults().string(forKey: "language")! 

    if let destination = segue.destination as? DocumentListTableViewController {
        let item = sender as! WhatEverTheTypeIs // change this to the real type
        destination.titlePassed = item.name.localized(lang: languageSelected)
        destination.requestedEntity = item.entityName
        destination.requestedSortBy = item.sortBy
        destination.requestedPredicate = item.predicate

    }
}

答案 2 :(得分:2)

在performSegue通话中,您正在发送CustomButton的新实例

performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())

因此在下一个视图控制器中,其参数将为零,您需要改为发送发送者。

performSegue(withIdentifier: "goToDocumentList", sender: sender)

您需要重写prepareForSegue才能调用它,而无需更改其签名,可以这样写:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let languageSelected = UserDefaults().value(forKey: "language") as! String

    if let destination = segue.destination as? DocumentListTableViewController {

        let myCustomButton = sender as! CustomButton

        destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
        destination.requestedEntity = myCustomButton.requestEntity
        destination.requestedSortBy = myCustomButton.requestSortBy
        destination.requestedPredicate = myCustomButton.requestPredicate

    }
}