ios - 当用户在详细 View Controller 中点击 `Back` 时触发一个函数

标签 ios swift uinavigationcontroller segue

当用户返回那个 VC 时,我需要刷新我的 collectionView,因为他/她在 detailVC 中所做的会影响以前的 VC 数据。我在 viewDidLoad()viewDidAppear() 中都尝试了 collectionView.reloadData() 我的 VCcollectionView 在里面。结果是,当用户在 detailVC 中点击 'Back' 时,viewDidLoad()viewDidAppear()不工作。因此,我尝试在 detailVC 中调用其中一个并实例化 firstVC(它具有 collectionView) 然后我收到一个运行时错误,提示 collectionView is nil。有什么想法吗? (顺便说一句,它们之间的 segue 是 ShowPush,我无法更改它,因为我必须在我的应用程序中进行此 segue 的转换。)

这是第一个VC:

class SkillsController: UIViewController{

    @IBOutlet weak var collectionView: UICollectionView!

    var TAGS: [TAG] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        let nib = UINib(nibName: "TagCell", bundle: nil)
        collectionView.register(nib, forCellWithReuseIdentifier: "tagCell")
        self.sizingCell = (nib.instantiate(withOwner: nil, options: nil) as NSArray).firstObject as! TagCell?
        self.loadMore()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("back to skills")
        self.TAGS = TagManager.shared.tagList
        collectionView.reloadData()
    }

}

TAGS 是我的数据,存储在 Realm 数据库中。

这是详细VC:

class SeeSelectedController: UICollectionViewController {

    var TAGS: [TAG] = []

    @IBOutlet weak var layout: FSQCollectionViewAlignedLayout!

    override func viewDidLoad() {
        super.viewDidLoad()

        if currentTab.shared.isSkill {
            self.title = "Selected Skills"
            //init tags
            let list = RealmManager.shared.skills
            if let list = list {
                for element in list {
                    TAGS.append(TAG(n: element.value!, iS: true))
                }
            }
            collectionView?.reloadData()
        }else{
            self.title = "Selected Needs"
            //init tags
            let list = RealmManager.shared.needs
            if let list = list {
                for element in list {
                    TAGS.append(TAG(n: element.value!, iS: true))
                }
            }
            collectionView?.reloadData()
        }

        let nib = UINib(nibName: "TagCell", bundle: nil)
        collectionView?.register(nib, forCellWithReuseIdentifier: "tagCell")
    }

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let item = TAGS[indexPath.row].name!
        let currentState = TAGS[indexPath.row].isSelected!
        TAGS[indexPath.row].isSelected = currentState ? false:true
        if currentState {
            print("deselect")
            //remove from realm
            RealmManager.shared.deleteItemFromList(type: getTypeOfTag(isSkill: currentTab.shared.isSkill), item: item)
        }else{
            print("select")
            //add to realm
            RealmManager.shared.addItemToList(type: getTypeOfTag(isSkill: currentTab.shared.isSkill), item: item)
        }
        if currentTab.shared.isSkill {
            let VC: SkillsController = storyboard?.instantiateViewController(withIdentifier: "SkillsController") as! SkillsController
            VC.viewDidAppear(true)
        }
        collectionView.reloadData()
        //addd
    }

}

那么它是如何工作的呢?在 SkillsVC 中,用户可以从池中选择一些标签,在 detailVC 中,即 SeeSelecteVC 他/她可以删除选定的标签。如您所见,它在 Realm 中不断变化。当用户在 detailVC 中删除一些标签并按下 Back 按钮时,删除的标签仍然看起来像在 SkillsVC 中选择的那样。但是,如果用户转到另一个 VC 并返回到 SkillsVC(通过这种方式 viewDidLoad() 将起作用),则似乎未选择删除的标签。就这样。

最佳答案

如果您正在寻找的只是在后退按钮上重新加载

您可以做的是创建您自己的自定义 UIBarButtonItem,这将使您从“详细信息 View Controller ”向后导航。添加您自己的后退按钮后,下一步应该为 UIBarBUttonItempop 添加一个 IBAction 您的“详细信息 View Controller ”。

在执行此操作之前,您应该创建一个委托(delegate),该委托(delegate)将在弹出发生之前执行,这将重新加载您的 UICollectionView

以下不是实现您想要的效果的最佳方式: 在你的第二个 View Controller 的 didSelectItem 中,你在这里创建了一个新的 View Controller ,你不应该强制调用 viewDidAppear。由于您正在创建一个新的 UIViewController,因此您没有引用您之前的 UIViewController,因此您的 UICollectionView 为 nil。

if currentTab.shared.isSkill {
     //remove the below lines and call the delegate here
     let VC: SkillsController = storyboard?.instantiateViewController(withIdentifier: "SkillsController") as! SkillsController
     VC.viewDidAppear(true)
}
collectionView.reloadData()

你应该做的是: 您应该使用委托(delegate)将回调发送到以前的 View Controller 或执行操作。 创建一个委托(delegate)-

使用第一种方法(使用你自己的后退按钮)-

protocol delegateVC{

    func reloadCollectionView()
}

class SeeSelectedController: UICollectionViewController{
    //add this inside this class
    var delegate : delegateVC?
    ...

   //implement your IBAction for back button and inside it-
    ...  {

        self.delegate.reloadCollectionView()
   }
}

或者我指出的第二种方法(只需更改您的 didSelectItem 它将重新加载 collectionView,根本无需担心后退按钮并省去麻烦,我强烈推荐这种方法)

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let item = TAGS[indexPath.row].name!
        let currentState = TAGS[indexPath.row].isSelected!
        TAGS[indexPath.row].isSelected = currentState ? false:true
        if currentState {
            print("deselect")
            //remove from realm
            RealmManager.shared.deleteItemFromList(type: getTypeOfTag(isSkill: currentTab.shared.isSkill), item: item)
        }else{
            print("select")
            //add to realm
            RealmManager.shared.addItemToList(type: getTypeOfTag(isSkill: currentTab.shared.isSkill), item: item)
        }
        if currentTab.shared.isSkill {
           self.delegate.reloadCollectionView()
        }
    }
}

在您的第一个 View Controller 中-

func reloadCollectionView(){
     collectionView.reloadData()
}

注意:在您的prepareForSegue中,请记住将详细 View Controller 的委托(delegate)设置为您的第一个 View Controller

关于ios - 当用户在详细 View Controller 中点击 `Back` 时触发一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40848228/

相关文章:

ios - 如何根据 UIView 背景颜色使用 if 语句

ios - GPUImage 过滤器组的问题

ios - iOS平台如何监控文件变化?

ios - UIView 宽度在第一次启动时显示不同

ios - 防止自定义容器中的 UINavigationBar 动画

ios - Objective-C 将导航栏添加到 rootview

iphone - 触发 UIApplicationDidBecomeActiveNotification 后会调用什么?

swift - 在 SwiftUI 中数据项发生变化时更新列表

ios - 二元运算符 + 不能应用于 CGfloat int 类型的操作数

iphone - 在 navigationController 上前后滑动