0

I want to reload only single cell after user select the contact (method didSelect contact). If the number of item in cell getting bigger, the process is getting slower. I also try to implement in DispatchQueue.main.async { code } and it still take some time to load.

cellForItemAt and noOfItemInSection (AddCell) - Total cell 4

var indexPaths = [IndexPath]()

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
   indexPaths.append(indexPath)

   if indexPath.item == 1 {
        let addCell = collectionView.dequeueReusableCell(withReuseIdentifier: CellId, for: indexPath) as! AddCell
        addCell.btnAdd.addTarget(self, action: #selector(handleOpenContact), for: .touchUpInside)
        addCell.invitees = invitees
        return addCell
    }
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }

cellForItemAt and noOfItemInSection (SubAddCell)

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: subAddId, for: indexPath) as! SubAddCell
        cell.delegate = self
        cell.invitee = invitees[indexPath.item]
        return cell
    }

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

didSelect (ContactPicker)

func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
        let invitee = Invitee()
        invitee.name = contact.givenName

        if contact.isKeyAvailable(CNContactPhoneNumbersKey) {
            for phoneNumber: CNLabeledValue in contact.phoneNumbers {
                let a = phoneNumber.value
                print("\(a.stringValue)")
                invitee.phoneNo = a.stringValue
            }
        }
        self.invitees.append(invitee)

        for index in self.indexPaths {
            if index == [0, 0] {
                print(index)
                self.collectionView?.reloadItems(at: [index])
            }
        }
    }

I have obtain the value of indexPaths at cellForItemAt method. If the invitee contains 5 items, the print(index) will print 19 values. I dont know why. Below is the image.

enter image description here

Design of the UI

enter image description here

How to optimize the reloadItems?

Any help is really appreciated. Many thanks.

Nizzam
  • 1,030
  • 3
  • 16
  • 29
  • can you describe the rest of your `cellForItemAtIndexPath` method? you only show that you handle the cell at index 1... whereas you clearly have 19 cells being used. What's the rest of the method? – jlmurph Oct 25 '17 at 04:00
  • @murphguy, it was only 4 cell. For that particular cell, have a `UICollectionView` inside it. I have update the questions. – Nizzam Oct 25 '17 at 04:15
  • Well therein lies your challenge. Collapsable cell animation/handling is rather heavy. So it depends on : do you use autolayout within the cell or not? is the content of the cell dynamic? are you loading images asyncronously via a seperate thread? those three questions should answer your question as to why your app is laggy. – jlmurph Oct 25 '17 at 14:24

2 Answers2

0

I think you have this indexPaths.append(indexPath) in cellForItemAt so that why the indexPaths can increase after reload data. You might use NSSet instead of NSArray to make sure your objects are unique.

And with this: cell.invitee = invitees[indexPath.item], did you implement didSet for invitee? If you did, I think need to prepare data in background queue first. E.g.

DispatchQueue(label: "queue").async {
  let image = <# process image here #>
  let name = <# process name here #>
  DispatchQueue.main.async {
    self.imageView.image = image
    self.label.text = name
  }
}

Hope my tips could help you!

Tai Le
  • 8,530
  • 5
  • 41
  • 34
  • I did implement didSet for `invitee`. NSSet need to be set as IndexPath ? I didnt get you. – Nizzam Oct 25 '17 at 06:35
  • -I guess your `didSet` take a lot of time to process data to fill to your UI elements. - And NSSet make sure your indexPaths are not duplicated! – Tai Le Oct 26 '17 at 02:24
0

Collectionviews are the most powerful UI tool of iOS, but if done wrong, or if misused (which happens, don't worry), they can be worse for your UX. . To view how this stuff is affected read up on XCode Tools and how to use them to debug your UI performance.

Important note to consider:

frame-by-frame operations (ie, loading your collectionviewcell, expanded, or unexpanded) should take no more than 17 ms to execute for smooth scrolling.

UICollectionView performance - _updateVisibleCellsNow

So you need to make your cells as simple and efficient as possible. That's the best place to start, especially if your expandable cells themselves contain complex subviews like collectionviews.

jlmurph
  • 1,050
  • 8
  • 17