add an item or cell having an array, in a collectionView

0

Greetings to all! I hope someone can solve my problem, I have my CollectionView, and in it I put a sampleObject, which contains an image and a label and a function to add these examples, this returns an array and I put it in my collection: and when I want to add a new object to said collection I do it from another ViewController, but I do not add anything to the collection I do not know what I'm doing wrong I'm new to this, someone mentioned that it depends on how the class where the collection collection object is instantiated, and which is it has to be initialized, but I have not found anything I put my code:

this is my object model:

   class SampleObjects: NSObject {

      var image: String?
      var name: String?

      init(name: String, image: String) {
          self.image = name
          self.name = image
          super.init()
   }

// funcion para crear los ejemplos de objetos
   static func sampleNewObject() -> [SampleObjects] {

    var objectos = [SampleObjetc]()

    let objetoUno = SampleObjects(name: "nombre", Image: "miImagen")
    objetos.append(objetoUno)

    return objetos

}

I place the instance of the object in the viewController where I have my collectionView:

  var misObjetos: [SampleObjects]?

I also create an instance of the object in the collectionViewCell to be able to place the data of the SampleObject and appear in the view and which are related to the properties within the collectionViewCell:

   var objetosEnCollection: SampleObjetos? {
    didSet {
        if let name = propiedadEnCollection?.name {
            nameImage.text = name
        }
        if let imageName = propiedadCollection?.image {
            image.image = UIImage(named: imageName)
        }
    }
}

and I put it in the section in my collectionView:

   func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    if collectionView == miCollectionView {
        if let countObjetos = misObjetos?.count {
            return countObjetos
        }
        return 0
    }

and then in the collection cell:

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

    if collectionView == instrumentCarousel {
        let cell: miColleccionCell = collectionView.dequeueReusableCell(withReuseIdentifier: carouselCellId, for: indexPath) as! miColleccionCell

        if let celda = misObjetos?[indexPath.item] {
           cell.misObjetos = celda
        }

        return cell
    }

I also access the data of the model so that I can add the function and colóco in the ViewController where my collectionView is:

 misObjetos = SampleObjects.sampleNewObject()

everything is fine here, it appears in the cell, if I add more objects to the array inside the function in SampleObjetc ... and it appears in the CollectionView ...

the detail is at this point ... I'm in another viewController, and I have a button, in which is going to add one more object in the array for the collectionView cell .. and I do the following ...

I urge the classes to call the collection where the new object will go

 var misObjetos: [SampleObjects]?

 var miColeccion: miCollectionView?
       // no se si tenga que inicializar aqui esta declaración si es asi no se como hacerlo...

and in the function of the button I do the following:

   @objc func addTrack()  {


    let objetosCollection = ViewController.miCollectionView

    let new = SampleObjects.init(name: "nombre", image: "miImagen")

    do {
        misObjetos.append(new)

        let item = misObjetos.count + 1
        let insertOnCollection = IndexPath(item: item, section: 0)
        objetosCollection?.insertItems(at: [insertOnCollection])

    }

    dismiss(animated: true, completion: nil)
}

and run the app, but when wanting to add the object does not put anything, maybe it is not the way to add an object to the collection, I've been looking for a solution and I have not found anything, I hope someone can remove this doubt. .. I use Swift 4, greetings to all

    
asked by Yan Cervantes 16.12.2017 в 00:44
source

1 answer

1

You have a couple of things that you should change. Your data model, you have it in a controller (CollectionView) and it should be there where you modify it. You initialize it and add it, consult it or remove elements, but you should not recreate an array with the new information and return it to them, because it will eliminate all of the above. The sending of the new model that you created in the ViewController to the CollectionView should be done with a protocol or using a delegate. In the ViewController you create the new thing and you pass it and that's where its function ends. The CollectionView should integrate it with the existing model and reload the collectionView.

Look at the names I give you, C ollectionView the controller, collectionView is the collectionView of C ollectionView.

The model is created like this, you do not need sampleNewObject ()

In CollectionView you define a property of your model, it does not need to be optional, you create it empty

var misObjetos: [SampleObjects] = []

The numberOfItemsInSection can now be simplified, since you know that myObjects exists always and you do not have to ensure if it is nil or not. If you only have a collectionView in the controller you can also avoid checking the collectionView. I understand that it only has one section.

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return misObjetos.count

}

In the cellForItemAt a bit of the same, you can avoid the check of the collectionView and to obtain the item to be shown, the optional one is not necessary, you can change the

let celda = misObjetos[indexPath.row]

We are going with the creation of a new element. The first thing is to know how the ViewController will pass the information to CollectionView. As I said or protocol or delegate. We will try with delegate, so in ViewController we have to create the delegate that points to the CollectionView type controller. Define the property in ViewController

var delegate: CollectionView?

You have not specified how you make the transition to ViewController, I imagine you will have a button somewhere, because you put this in the action (or how you do)

let vc = ViewController()
vc.delegate = self
self.present(vc,animated: true, completion: nil)

In the ViewController you will have whatever it takes to insert the data you want in any way, the fact is that when you have that information you have to create a new element for your data model that you will create with your init that you already have created

let nuevo = SampleObjects(name:"Yan", image:"foto")

and now I pass it to the delegate and how? I have to create a method that receives this new element so I'll call it new Element (yes, I'm very original) and you pass it this way

self.delegate.nuevoElemento(item: nuevo)
//y cerramos ViewController, que ya ha hecho suficiente
self.dismiss(animated: true, completion: nil)

Now we have to implement the new Element in the delegate, which is CollectionView, so you create a new method in CollectionView

func nuevoElemento(item: SampleObjects) {
    //me han pasado el nuevo elemento, solo tengo que añadirlo a lo que ya tengo
    self.misObjetos.append(item)
    //recargo la collectionView
    self.collectionView.reloadData()
}

It could happen that the collectionView.reloadData () does not do anything, sometimes it has happened to me that the data is and does not reload, in that case instead of reloadData you tell the collectionView that you have inserted a new element and it is already I'll do whatever it takes, in which case I'd have to change this:

func nuevoElemento(item: SampleObjects) {
    //me han pasado el nuevo elemento, solo tengo que añadirlo a lo que ya tengo
    self.misObjetos.append(item)
    //le digo a la collectionView que inserte un nuevo elemento
    let ip = NSIndexPath(row: self.misObjectos.count - 1, section:0)
    self.collectionView.insertItemsAtIndexPaths([ip])
}

Version with protocol: We create a protocol, you can write it where you want, I usually put it in the issuing controller, in this case ViewController.

protocol CollectionViewProtocol {
    func nuevoElemento(item: SampleObjects)
}

Now you have to have a property that is of the protocol type, so we will not use the delegate from before and you need a property that is for example

var collectionControllerProtocol: CollectionViewProtocol?

when we create the ViewController to show it, instead of the delegate we have to pass the protocol

let vc = ViewController()
vc. collectionControllerProtocol = self
self.present(vc,animated: true, completion: nil)

In the ViewController, once you know the name and the image you want to insert, you create the element in the same way as before and then you execute the protocol method instead of the delegate

self.collectionControllerProtocol?.nuevoElemento(item: nuevo)

Now you just have to have CollectionView implement the protocol.

extension CollectionView: CollectionViewProtocol {
func nuevoElemento(item: SampleObjects) {
 //la misma función que esta para el delegado
}
    
answered by 16.12.2017 / 18:50
source