单击删除按钮,Swift

时间:2017-08-16 04:43:03

标签: ios swift uicollectionview

我在集合视图控制器中显示图像。当点击单元格时,我将这些图像传递给页面视图控制器,用户可以选择删除或添加图像描述,如下图所示。

enter image description here

当用户点击删除按钮时,我会删除页面(或视图控制器)(就像在Apple iOS照片应用程序中单击删除按钮时所看到的行为一样)。

我尝试通过将一个空视图控制器数组传递给pageViewController(参见代码A)来实现它,这导致了一个错误 The number of view controllers provided (0) doesn't match the number required (1) for the requested transition这是有道理的。

我是否走在正确的轨道上,如果是的话,我该如何解决这个问题? 如果没有,是否有更好的方法来实现同样的目标?

代码A:取自代码B

pageVC.setViewControllers([], direction: .forward, animated: true, completion: nil)

代码B:取自UserPickedImageVC

func deleteCurrentImageObject(){

    guard let controllers = self.navigationController?.viewControllers else{
        return
    }
    for viewController in controllers {
        if viewController.className == "UserPickedImagesVC"{

            let vc              =   viewController as! UserPickedImagesVC
            let objectCount     =   vc.imageObjectsArray.count

            guard objectCount > 0 && objectCount >= itemIndex else {
                return
            }

            vc.imageObjectsArray.remove(at: itemIndex) //  Removing imageObject from the array


            if let pageVC = vc.childViewControllers[0] as? UIPageViewController {
                pageVC.setViewControllers([], direction: .forward, animated: true, completion: nil)

            }

        }
    }
} 

故事板

enter image description here

这是完整的代码(除了一些自定义的UICollectionViewCell):

UserPickedImagesCVC.swift

import UIKit
import ImagePicker
import Lightbox

private let imageCellId     =   "imageCell"
private let addCellId       =   "addImagesCell"

class UserPickedImagesCVC: UICollectionViewController, ImagePickerDelegate, UserPickedImagesVCProtocol {

    let imagePickerController = ImagePickerController()
    //var userPickedImages = [UIImage]()
    var userPickedImages = [ImageObject]()

    override func viewDidLoad() {
        super.viewDidLoad()

        imagePickerController.delegate = self as ImagePickerDelegate

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Register cell classes
        self.collectionView!.register(ImageCVCell .self, forCellWithReuseIdentifier: imageCellId)
        self.collectionView!.register(ImagePickerButtonCVCell.self, forCellWithReuseIdentifier: addCellId)

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return userPickedImages.count + 1
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let item = indexPath.item
        print("item: \(item)")
        if item < userPickedImages.count {

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imageCellId, for: indexPath) as! ImageCVCell
            let userPickedImageObject = userPickedImages[item]
            //cell.showImagesButton.setImage(userPickedImage, for: .normal)

            cell.showImagesButton.setImage(userPickedImageObject.image, for: .normal)
            cell.showImagesButton.addTarget(self, action: #selector(showAlreadyPickedImages), for: .touchUpInside)
            //cell.addButton.addTarget(self, action: #selector(showAlreadyPickedImages), for: .touchUpInside)

            return cell
        }

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: addCellId, for: indexPath) as! ImagePickerButtonCVCell
        cell.addButton.addTarget(self, action: #selector(showImagePickerController), for: .touchUpInside)
        return cell


        // Configure the cell
    }


    //Function shows imagePicker that helps in picking images and capturing images with camera
    func showImagePickerController(){
        print("showImagePickerController func called")
        //self.present(imagePickerController, animated: true, completion: nil)
        self.navigationController?.pushViewController(imagePickerController, animated: true)
    }


    func showAlreadyPickedImages(){
        let vc = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImagesVC") as! UserPickedImagesVC
        //vc.contentImages = userPickedImages
        vc.imageObjectsArray = userPickedImages
        vc.showingAlreadySavedImages = true
        self.navigationController?.pushViewController(vc, animated: true)
    }

    func setImagesInCells(imageObjects : [ImageObject]){
        print("setImagesInCells func called in CVC")
        userPickedImages += imageObjects
        collectionView?.reloadData()
    }


    // MARK: - ImagePickerDelegate

    func cancelButtonDidPress(_ imagePicker: ImagePickerController) {
        imagePicker.dismiss(animated: true, completion: nil)
    }

    func wrapperDidPress(_ imagePicker: ImagePickerController, images: [UIImage]) {
        guard images.count > 0 else { return }

        let lightboxImages = images.map {
            return LightboxImage(image: $0)
        }

        let lightbox = LightboxController(images: lightboxImages, startIndex: 0)
        imagePicker.present(lightbox, animated: true, completion: nil)
    }

    func doneButtonDidPress(_ imagePicker: ImagePickerController, images: [UIImage]) {
        imagePicker.dismiss(animated: true, completion: nil)

        let vc = storyboard?.instantiateViewController(withIdentifier: "userPickedImagesVC") as! UserPickedImagesVC

        //vc.contentImages = images
        vc.imageObjectsArray =  convertImagesToImageObjects(images)

        //self.present(vc, animated: true, completion: nil)
        self.navigationController?.pushViewController(vc, animated: true)
    }

    func convertImagesToImageObjects(_ imagesArray : [UIImage]) -> [ImageObject]{
        var imageObjects = [ImageObject]()
        for image in imagesArray{
            var imageObject = ImageObject()
            imageObject.image = image
            imageObject.imageDescription = ""
            imageObjects.append(imageObject)
        }
        return imageObjects
    }

}

UserPickedImagesVC.swift

import UIKit

protocol UserPickedImagesVCProtocol{
    func setImagesInCells(imageObjects : [ImageObject])
}

class ImageObject : NSObject{
    var imageDescription :  String?
    var image            :  UIImage?
}


class UserPickedImagesVC: UIViewController, UIPageViewControllerDataSource {

    var pageViewController  :   UIPageViewController?
    let placeholderText     =   "Image description.."

    var imageObjectsArray =   [ImageObject]()
    var delegate            :   UserPickedImagesVCProtocol!
    var showingAlreadySavedImages = false



    override func viewDidLoad() {
        super.viewDidLoad()
        edgesForExtendedLayout = [] // To avoid view going below nav bar
        //self.delegate = self.navigationController?.viewControllers


        // Do any additional setup after loading the view, typically from a nib.
        if showingAlreadySavedImages{
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneTapped))
        }else{
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(saveTapped))
        }
        // createImageAndDescriptionDict()
        createPageViewController()
        setupPageControl()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func createPageViewController(){
        print("createPageViewController func called")
        let pageController = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImagesPageController") as! UIPageViewController

        pageController.dataSource = self

        if imageObjectsArray.count > 0 {
            let firstController = getItemController(0)
            let startingViewControllers = [firstController]

            pageController.setViewControllers(startingViewControllers as! [UIViewController], direction: .forward, animated: false, completion: nil)

        }

        pageViewController = pageController
        addChildViewController(pageViewController!)
        self.view.addSubview((pageViewController?.view)!)
        pageViewController?.didMove(toParentViewController: self)
    }


    // Creata the appearance of pagecontrol
    func setupPageControl(){

        let appearance = UIPageControl.appearance()
        appearance.pageIndicatorTintColor = UIColor.gray
        appearance.currentPageIndicatorTintColor = UIColor.white
        appearance.backgroundColor = UIColor.darkGray

    }



    //MARK: Delagate methods
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let itemController = viewController as! UserPickedImageVC

        if itemController.itemIndex > 0 {
            return self.getItemController(itemController.itemIndex-1)
        }
        return nil
    }


    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let itemController = viewController as! UserPickedImageVC

        if itemController.itemIndex + 1 < imageObjectsArray.count{

            return getItemController(itemController.itemIndex+1)

        }

        return nil
    }


    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return imageObjectsArray.count
    }


    func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        return 0
    }


    func currentControllerIndex() -> Int{
        let pageItemController = self.currentControllerIndex()

        if let controller = pageItemController as? UserPickedImageVC{
            return controller.itemIndex
        }

        return -1
    }


    func currentController() -> UIViewController?{
        if(self.pageViewController?.viewControllers?.count)! > 0{
            return self.pageViewController?.viewControllers?[0]
        }
        return nil
    }


    func getItemController(_ itemIndex:Int) -> UserPickedImageVC?{

        if itemIndex < imageObjectsArray.count{
            let pageItemController = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImageVC") as! UserPickedImageVC

            pageItemController.itemIndex = itemIndex
            //pageItemController.imageName = imageObjectsArray[itemIndex]

            //pageItemController.imageToShow = imageObjectsArray[itemIndex]
            //pageItemController.imageToShow = getImageFromImageDescriptionArray(itemIndex, imagesAndDescriptionArray)
            pageItemController.imageObject  =   imageObjectsArray[itemIndex]
            pageItemController.itemIndex    =   itemIndex
            pageItemController.showingAlreadySavedImage = showingAlreadySavedImages
            print("Image Name from VC: \(imageObjectsArray[itemIndex])")
            return pageItemController
        }
        return nil
    }





    // Passing images back to Collection View Controller when save button is tapped

    func saveTapped(){

        let viewControllers = self.navigationController?.viewControllers
        //print("viewControllers: \(viewControllers)")

        if let destinationVC = viewControllers?[0]{
            self.delegate = destinationVC as! UserPickedImagesVCProtocol
            //self.delegate.setImagesInCells(images : imageObjectsArray)
            self.delegate.setImagesInCells(imageObjects : imageObjectsArray)
            self.navigationController?.popToViewController(destinationVC, animated: true)
        }

    }

    func doneTapped(){
        let viewControllers = self.navigationController?.viewControllers

        if let destinationVC = viewControllers?[0] {
            self.navigationController?.popToViewController(destinationVC, animated: true)
        }
    }

}

UserPickedImageVC.swift

    import UIKit
import ImageScrollView

extension UIViewController {
    var className: String {
        return NSStringFromClass(self.classForCoder).components(separatedBy: ".").last!;
    }
}

class UserPickedImageVC: UIViewController, UITextViewDelegate {



    var itemIndex : Int             = 0
    var imageDescription : String   = ""
    var imageScrollView = ImageScrollView()
    var imageDescriptionTextView : UITextView!
    var imageToShow : UIImage!

    var imageObject : ImageObject?        
    var deleteButton = UIButton(type: .system)
    var showingAlreadySavedImage = false

    var pageViewController : UIPageViewController!




    override func viewDidLoad() {
        super.viewDidLoad()


        edgesForExtendedLayout = [] // To avoid images going below the navigation bars

        pageViewController = self.parent as! UIPageViewController

        setConstraints()
        setImageAndDescription()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    //MARK: TextView delegate methods
    func textViewDidBeginEditing(_ textView: UITextView)
    {
        if (imageDescriptionTextView.text == "Image description..")
        {
            imageDescriptionTextView.text = ""
            imageDescriptionTextView.textColor = .black
        }
        imageDescriptionTextView.becomeFirstResponder() //Optional
    }

    func textViewDidEndEditing(_ textView: UITextView)
    {
        let imageDescription = imageDescriptionTextView.text

        if (imageDescription == "")
        {
            imageDescriptionTextView.text = "Image description.."
            imageDescriptionTextView.textColor = .lightGray
        }
        imageObject?.imageDescription = imageDescription
        updateImageObject(imageObject!)
        imageDescriptionTextView.resignFirstResponder()
    }



    //MARK: Private Methods
    func setImageAndDescription(){

        if let imageToDisplay = imageObject?.image{
            imageScrollView.display(image: imageToDisplay)  // Setting Image
        }
        imageDescriptionTextView.text = imageObject?.imageDescription    // Setting Description

    }

    // Function to update imageObject in UserPickedImagesVC
    func updateImageObject(_ imageObject: ImageObject){
        guard let controllers = self.navigationController?.viewControllers else{
            return
        }
        for viewController in controllers {
            if viewController.className == "UserPickedImagesVC" {
                let vc = viewController as! UserPickedImagesVC
                vc.imageObjectsArray[itemIndex] = imageObject

            }
        }
    }


    // Function to delete imageObject from UserPickedImagesVC
    func deleteCurrentImageObject(){

        guard let controllers = self.navigationController?.viewControllers else{
            return
        }
        for viewController in controllers {
            if viewController.className == "UserPickedImagesVC"{

                let vc              =   viewController as! UserPickedImagesVC
                let objectCount     =   vc.imageObjectsArray.count

                guard objectCount > 0 && objectCount >= itemIndex else {
                    return
                }

                vc.imageObjectsArray.remove(at: itemIndex) //  Removing imageObject from the array


                if let pageVC = vc.childViewControllers[0] as? UIPageViewController {
                    pageVC.setViewControllers([], direction: .forward, animated: true, completion: nil)

                }

            }
        }
    }

    func showOrHideDeleteButton(){
        if showingAlreadySavedImage{
            print("deleteButton.isNotHidden")
            deleteButton.isHidden   = false
        }else{
            print("deleteButton.isHidden")
            deleteButton.isHidden   = true
        }
    }


    func setConstraints(){
        let viewSize    =   self.view.frame.size
        let viewWidth   =   viewSize.width
        let viewHeight  =   viewSize.height
        print("viewWidth: \(viewWidth), viewHeight: \(viewHeight)")

        view.addSubview(imageScrollView)
        imageScrollView.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight)
        deleteButton.tintColor = Colors.iOSBlue
        deleteButton.setImage(#imageLiteral(resourceName: "delete"), for: .normal)
        deleteButton.backgroundColor = Colors.white
        deleteButton.layer.cornerRadius = 25
        deleteButton.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

        //deleteButton.currentImage.
        deleteButton.imageView?.tintColor = Colors.iOSBlue
        deleteButton.addTarget(self, action: #selector(deleteCurrentImageObject), for: .touchUpInside)
        deleteButton.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(deleteButton)
        showOrHideDeleteButton()

        imageDescriptionTextView = UITextView()
        imageDescriptionTextView.delegate = self as! UITextViewDelegate
        imageDescriptionTextView.text = "Image description.."
        imageDescriptionTextView.textColor = .lightGray

        //imageScrollView.clipsToBounds = true

        imageDescriptionTextView.translatesAutoresizingMaskIntoConstraints = false
        //imageDescriptionTextView.backgroundColor = UIColor.white.withAlphaComponent(0.8)
        imageDescriptionTextView.backgroundColor = UIColor.white
        imageDescriptionTextView.layer.cornerRadius = 5
        imageDescriptionTextView.layer.borderColor = UIColor.lightGray.cgColor
        imageDescriptionTextView.layer.borderWidth = 0.5
        view.addSubview(imageDescriptionTextView)


        let viewsDict = [
            "imageDescriptionTextView"  :   imageDescriptionTextView,
            "deleteButton"              :   deleteButton
            ] as [String:Any]

        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-5-[imageDescriptionTextView]-70-|", options: [], metrics: nil, views: viewsDict))
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[imageDescriptionTextView(50)]-5-|", options: [], metrics: nil, views: viewsDict))
        imageDescriptionTextView.sizeThatFits(CGSize(width: imageDescriptionTextView.frame.size.width, height: imageDescriptionTextView.frame.size.height))

        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[deleteButton(50)]-5-|", options: [], metrics: nil, views: viewsDict))
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[deleteButton(50)]-5-|", options: [], metrics: nil, views: viewsDict))
    }

}

1 个答案:

答案 0 :(得分:2)

UserPickedImageVC.swift

中创建回调属性

typealias DeleteCallBack =(int) - &gt;空隙

...
var itemIndex : Int             = 0
var deleteCallBack:DeleteCallBack?
...

func deleteCurrentImageObject(){
    self.deleteCallBack?(self.itemIndex)
}
UserPickedImagesVC.swift

中的

func getItemController(_ itemIndex:Int) -> UserPickedImageVC?{

    if itemIndex < imageObjectsArray.count{
        let pageItemController = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImageVC") as! UserPickedImageVC

        pageItemController.itemIndex = itemIndex

        pageItemController.imageObject  =   imageObjectsArray[itemIndex]
        pageItemController.itemIndex    =   itemIndex
        pageItemController.showingAlreadySavedImage = showingAlreadySavedImages
        print("Image Name from VC: \(imageObjectsArray[itemIndex])")
        pageItemController.deleteCallBack = {
            [weak self] (index) -> Void in
            self?.deleteItemAt(index: index)
        }
        return pageItemController
    }
    return nil
}

func deleteItemAt(index: Int) {
   if (imageObjectsArray.count > 1) {
       imageObjectsArray.remove(at: itemIndex)
       self.pageViewController.dataSource = nil;
       self.pageViewController.dataSource = self;
       let firstController = getItemController(0)
       let startingViewControllers = [firstController]

       pageViewController.setViewControllers(startingViewControllers as! [UIViewController], direction: .forward, animated: false, completion: nil)
   } else {
        //redirect here
        _ = navigationController?.popViewController(animated: true)
   }
}