Search code examples
iosswiftuicollectionviewchildviewcontroller

Cannot reorder Collection View cells


I have a Split View Controller and when the user clicks a cell in the Table View, the app shows a View Controller with a Container View and a Segment Control to switch between two children view controllers.

The first child view controller is a Collection View Controller. In every cell of the Collection View there is a word.

The view looks like this:

view screen

I add the child view controller programmatically with this code (from the Detail View Controller, the container of Subviews):

override func viewDidLoad() {


    self.currentViewController = self.storyboard?.instantiateViewController(withIdentifier: "WordCollectionViewControllerID")
    (self.currentViewController as! WordCollectionViewController).text = self.text
    self.currentViewController?.view.translatesAutoresizingMaskIntoConstraints = false
    self.addChildViewController(self.currentViewController!)
    self.addSubview(subView: self.currentViewController!.view, toView: self.textContainerView)
    self.currentViewController?.view.layoutIfNeeded()
    self.currentViewController?.didMove(toParentViewController: self)

    super.viewDidLoad()

}

func addSubview(subView: UIView, toView parentView: UIView) {
    parentView.addSubview(subView)

    var viewBindingsDict = [String: AnyObject]()
    viewBindingsDict["subView"] = subView
    parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[subView]|", options: [], metrics: nil, views: viewBindingsDict))
    parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[subView]|", options: [], metrics: nil, views: viewBindingsDict))
}

Here is the code for switch between the two children views with the segmented control:

@IBAction func changeChildViewController(_ sender: UISegmentedControl) {
    if sender.selectedSegmentIndex == 0 {
        let newViewController = self.storyboard?.instantiateViewController(withIdentifier: "WordCollectionViewControllerID")
        (newViewController as! WordCollectionViewController).text = self.text
        newViewController!.view.translatesAutoresizingMaskIntoConstraints = false
        cycle(from: self.currentViewController!, to: newViewController!)
        self.currentViewController = newViewController
        print("Reorder")
    } else {
        let newViewController = self.storyboard?.instantiateViewController(withIdentifier: "NavigationControllerEditTextViewControllerID")
        (newViewController?.childViewControllers[0] as! EditTextViewController).text = self.text
        newViewController!.view.translatesAutoresizingMaskIntoConstraints = false
        cycle(from: self.currentViewController!, to: newViewController!)
        self.currentViewController = newViewController
        print("Edit")
    }
}

func cycle(from: UIViewController, to: UIViewController) {
    from.willMove(toParentViewController: nil)
    self.addChildViewController(to)

    self.addSubview(subView: to.view, toView: self.textContainerView)

    to.view.layoutIfNeeded()

    from.view.removeFromSuperview()

    from.removeFromParentViewController()
    to.didMove(toParentViewController: self)
}

To be able to reorder the cells I have implemented this method for my custom CollectionViewController class:

override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {

    // Swap values if sorce and destination
    let change = textArray[sourceIndexPath.row]


    textArray.remove(at: sourceIndexPath.row)
    textArray.insert(change, at: destinationIndexPath.row)


    // Save changes in Core Data
    text?.reordered_text = textArray.joined(separator: " ")

    (UIApplication.shared.delegate as! AppDelegate).saveContext()


    collectionView.reloadData()
}

The problem is that when I click the Table View Cell and the app shows the Container View with the Collection View Controller embedded, I can't reorder the cells,and to be able to do this I have to change the Child (with the Segmented Control) and then return to the Collection View.

How can I solve this problem?


Solution

  • Try to implement these methods:

    func beginInteractiveMovementForItem(at: IndexPath) -> Bool
    func updateInteractiveMovementTargetPosition(targetPosition: CGPoint)
    func endInteractiveMovement()
    func cancelInteractiveMovement()
    

    You can follow this tutorial: http://nshint.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/