菜鸟教程小白 发表于 2022-12-11 20:22:53

ios - 如何在不重新加载标题的情况下重新加载 UICollectionView 中的单元格?


                                            <p><p>我正在尝试根据用户在标题中的 textField 中输入的内容来更新 UICollectionView 中单元格的内容。我在这里查看了其他类似的问题,但他们的答案似乎都不起作用。我什至尝试实现 UICollectionView 的扩展,该扩展通过该部分中的每个单元格尝试重新加载其数据,但这会导致崩溃的数量用户进入 textField 后,单元格会发生变化</p>

<p>我试图解决问题的功能,我只有一个部分,所以我在该部分中进行了硬编码</p>

<pre><code>    @objc func textFieldDidChange(){
      guard(!(feedSearchBar.text?.isEmpty)!) else{
            VC.currentTagsArray = VC.genericTagsArray
            VC.feedScreenCollectionView.reloadData()
            return
      }
      VC.currentTagsArray = VC.genericTagsArray.filter({letter -&gt; Bool in
            if feedSearchBar.text!.count &gt; letter.count{
                return false
            }
            let stringRange = letter.index(letter.startIndex, offsetBy: feedSearchBar.text!.count)
            let subword = letter[..&lt;stringRange]
            return subword.lowercased().contains(feedSearchBar.text!.lowercased())

      })

      if VC.currentTagsArray.isEmpty{
            VC.currentTagsArray.insert(feedSearchBar.text!, at: 0)
      }
    VC.feedScreenCollectionView.reloadItems(inSection: 0)
   }

extension UICollectionView{
    func reloadItems(inSection section:Int = 0) {
      print(&#34;made it to reload&#34;)
      for i in 0..&lt;self.numberOfItems(inSection: section){
      self.reloadItems(at: )
      }
    }
}
</code></pre>

<p>这是项目的全部代码</p>

<pre><code>import UIKit

class ViewController: UIViewController,UICollectionViewDelegateFlowLayout,UICollectionViewDelegate,UICollectionViewDataSource,printDelegateWorkedDelegate,updateCollectionView{

    func updateCollectionView() {
      self.feedScreenCollectionView.reloadData()
    }

    func printDelegateWorkedDelegate() {
      print(&#34;The delegate worked&#34;)
    }

    var genericTagsArray: = [&#34;tag1&#34;,&#34;tag2&#34;,&#34;tag3&#34;,&#34;tag4&#34;,&#34;tag5&#34;,&#34;tag6&#34;,&#34;tag7&#34;,&#34;tag8&#34;,&#34;tag9&#34;,&#34;tag10&#34;,&#34;tag11&#34;,&#34;tag12&#34;,&#34;A&#34;,&#34;B&#34;,&#34;C&#34;,&#34;D&#34;,&#34;E&#34;,&#34;F&#34;,&#34;G&#34;,&#34;Ab&#34;,&#34;Abc&#34;,&#34;za&#34;,&#34;tag1&#34;,&#34;tag2&#34;,&#34;tag3&#34;,&#34;tag4&#34;,&#34;tag5&#34;,&#34;tag6&#34;,&#34;tag7&#34;,&#34;tag8&#34;,&#34;tag9&#34;,&#34;tag10&#34;,&#34;tag11&#34;,&#34;tag12&#34;,&#34;A&#34;,&#34;B&#34;,&#34;C&#34;,&#34;D&#34;,&#34;E&#34;,&#34;F&#34;,&#34;G&#34;,&#34;Ab&#34;,&#34;Abc&#34;,&#34;za&#34;]
    var currentTagsArray: = ()
    var tagsSelected: = ()
    let keyboardSlider = KeyboardSlider()

    var header:feedViewHeader = feedViewHeader()

    @IBOutlet weak var feedScreenCollectionView: UICollectionView!

    override func viewDidLoad() {
      super.viewDidLoad()
      keyboardSlider.subscribeToKeyboardNotifications(view: view)
      currentTagsArray = genericTagsArray

      let viewTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(feedViewHeader.viewTapped(gestureRecognizer:)))
      viewTapGestureRecognizer.cancelsTouchesInView = false
      self.feedScreenCollectionView.addGestureRecognizer(viewTapGestureRecognizer)

      feedScreenCollectionView.delegate = self
      //
      feedScreenCollectionView.dataSource = self
      //

      let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
      layout.sectionInset = UIEdgeInsets(top: 5, left: 1, bottom: 0, right: 1)
      layout.minimumLineSpacing = 0
      layout.headerReferenceSize = CGSize(width: 50, height: 75)

      layout.sectionHeadersPinToVisibleBounds = true
      feedScreenCollectionView.collectionViewLayout = layout
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -&gt; CGSize {
            return CGSize(width: 50, height: 75)
    }
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -&gt; UICollectionReusableView {
                header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: &#34;feedViewHeader&#34;, for: indexPath) as! feedViewHeader
            header.VC = self
      return header

    }
    //


    //Data Source
    func numberOfSections(in collectionView: UICollectionView) -&gt; Int {
      return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -&gt; Int {
      return currentTagsArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -&gt; UICollectionViewCell {
      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: &#34;feedViewCell&#34;, for: indexPath) as! feedViewCell
      cell.feedImageView.backgroundColor = .blue
      cell.feedImageView.clipsToBounds = true
      cell.feedImageView.layer.cornerRadius = CGFloat((cell.feedImageView.frame.width)/5)
      cell.feedLabel.text = currentTagsArray
      return cell
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -&gt; CGFloat {
      return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -&gt; CGFloat{
      return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -&gt; CGSize {
      let collectionViewWidth = collectionView.bounds.width/4.0
      let collectionViewHeight = collectionViewWidth
      return CGSize(width: collectionViewWidth-4, height: collectionViewHeight+25)
    }
    var lastContentOffset:CGFloat = 0

    func scrollViewDidScroll(_ scrollView: UIScrollView) {

      if self.lastContentOffset &gt; self.feedScreenCollectionView.contentOffset.y &amp;&amp; self.feedScreenCollectionView.contentOffset.y &gt; 0 &amp;&amp; self.feedScreenCollectionView.contentOffset.y &lt; self.feedScreenCollectionView.frame.maxY {
            self.lastContentOffset = scrollView.contentOffset.y
            header.isHidden = false
      }
      else if (self.lastContentOffset &lt; self.feedScreenCollectionView.contentOffset.y) &amp;&amp; (self.feedScreenCollectionView.contentOffset.y &lt; self.feedScreenCollectionView.frame.maxY) &amp;&amp; (self.feedScreenCollectionView.contentOffset.y &gt; 0){
            print(&#34;you scrolled down,content offSet: \(scrollView.contentOffset.y)-&gt;\(self.feedScreenCollectionView.contentOffset.y)&#34;)
            header.isHidden = true
      }
      else{
            self.lastContentOffset = scrollView.contentOffset.y
            print(&#34;content offSet: \(scrollView.contentOffset.y)&#34;)
            print(&#34;Nothing happened&#34;)
            //self.headerDelegate?.hideHeaderView(hide: true)
      }


    }

    override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(animated)
      NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    var offsetY:CGFloat = 0

    @objc func keyboardFrameChangeNotification(notification: Notification) {
    }


}


class feedViewCell:UICollectionViewCell{

    @IBOutlet weak var feedImageView: UIImageView!
    @IBOutlet weak var feedLabel: UILabel!

    let keyboardSlider = KeyboardSlider()

    override func awakeFromNib() {
      super.awakeFromNib()
      feedLabel.translatesAutoresizingMaskIntoConstraints = false
      feedImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
      feedImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
      feedImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
      feedImageView.bottomAnchor.constraint(equalTo: self.feedLabel.topAnchor).isActive = true

      feedImageView.translatesAutoresizingMaskIntoConstraints = false
      feedLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
      feedLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
      feedLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
      feedLabel.topAnchor.constraint(equalTo: self.feedImageView.bottomAnchor).isActive = true
      feedLabel.textAlignment = .center

    }

}




class feedViewHeader:UICollectionReusableView,UITextFieldDelegate,UICollectionViewDelegate{

    @IBOutlet weak var feedSearchBar: UITextField!

    var delegateWorked:printDelegateWorkedDelegate?
    var updateCV:updateCollectionView?


    var VC:ViewController!
    var collectionView:UICollectionView?
    var stringToBeSet = &#34;String to be set&#34;

    override func awakeFromNib() {
      super.awakeFromNib()

      feedSearchBar.delegate = self
      feedSearchBar.autocorrectionType = .no
      feedSearchBar.keyboardType = .default
          feedSearchBar.addTarget(self, action: #selector(feedViewHeader.textFieldDidChange), for: .editingChanged)
      self.feedSearchBar.borderStyle = .roundedRect
      self.feedSearchBar.layer.borderColor = UIColor.black.cgColor
      self.feedSearchBar.layer.borderWidth = 4
      var searchBarHeight = self.feedSearchBar.bounds.height
      self.feedSearchBar.placeholder = &#34;Tap To Search&#34;
      self.feedSearchBar.returnKeyType = .search
      self.feedSearchBar.rightViewMode = .always
    }


    @objc func viewTapped(gestureRecognizer:UIGestureRecognizer){

      iffeedSearchBar.isFirstResponder{
            feedSearchBar.resignFirstResponder()
      }
    }

   func textFieldShouldReturn(_ textField: UITextField) -&gt; Bool {
      textField.resignFirstResponder()
   VC.feedScreenCollectionView.reloadData()

    //VC.feedScreenCollectionView.reloadSections()
    return true
    }

    /// Helper to dismiss keyboard
    @objc func didStopEditing() {
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
      UIView.setAnimationCurve(UIViewAnimationCurve.easeInOut)
      UIView.animate(withDuration: 0.2) {
            self.VC.view.frame.origin.y = 0
      }
    }
    @objc func textFieldDidChange(){
      guard(!(feedSearchBar.text?.isEmpty)!) else{
            VC.currentTagsArray = VC.genericTagsArray
            VC.feedScreenCollectionView.reloadData()
            return
      }

      VC.currentTagsArray = VC.genericTagsArray.filter({letter -&gt; Bool in
         if feedSearchBar.text!.count &gt; letter.count{
                return false
            }
            let stringRange = letter.index(letter.startIndex, offsetBy: feedSearchBar.text!.count)
            let subword = letter[..&lt;stringRange]
            return subword.lowercased().contains(feedSearchBar.text!.lowercased())

      })

      if VC.currentTagsArray.isEmpty{
            VC.currentTagsArray.insert(feedSearchBar.text!, at: 0)
      }
    VC.feedScreenCollectionView.reloadItems(inSection: 0)
   }
}

extension Notification.Name{
    static let showKeyboard = Notification.Name(&#34;showKeyboard&#34;)
}
class KeyboardSlider: NSObject {
    // variables to hold and process information from the view using this class
    weak var view: UIView?

    @objc func keyboardWillShow(notification: NSNotification) {
      // method to move keyboard up
      // view?.frame.origin.y = 0 - getKeyboardHeight(notification as Notification)
      print(&#34;made it to keyboard will show&#34;)
    }

    func getKeyboardHeight(_ notification:Notification) -&gt; CGFloat {
      // get exact height of keyboard on all devices and convert to float value to return for use
      let userInfo = notification.userInfo
      let keyboardSize = userInfo! as! NSValue
      return keyboardSize.cgRectValue.height
    }

    func subscribeToKeyboardNotifications(view: UIView) {
      // assigning view to class&#39; counterpart
      self.view = view
      // when UIKeyboardWillShow do keyboardWillShow function
      NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
    }

    func unsubscribeFromKeyboardNotifications() {
      NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
    }
}

class blankView:UICollectionReusableView{

}

extension UICollectionView{
    func reloadItems(inSection section:Int = 0) {
      print(&#34;made it to reload&#34;)
      for i in 0..&lt;self.numberOfItems(inSection: section){
      self.reloadItems(at: )
      }
    }
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>你可以调用方法</p>

<p><strong>Objective-C</strong></p>

<pre><code>- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths
</code></pre>

<p><strong> swift </strong></p>

<pre><code>func reloadItems(at indexPaths: )
</code></pre>

<p>您可以在其中传递要更新的 indexPaths 数组。
更多信息请访问 <a href="https://developer.apple.com/documentation/uikit/uicollectionview/1618055-reloaditemsatindexpaths" rel="noreferrer noopener nofollow">Apple Documentation</a> </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何在不重新加载标题的情况下重新加载 UICollectionView 中的单元格?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/51409171/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/51409171/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何在不重新加载标题的情况下重新加载 UICollectionView 中的单元格?