微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过 UIButton 使用自定义 TableViewCell 添加到收藏夹并保存到 UserDefaults

如何解决通过 UIButton 使用自定义 TableViewCell 添加到收藏夹并保存到 UserDefaults

目标:在自定义 TableViewCell 中创建一个添加到收藏夹”按钮,然后将收藏夹列表保存到 UserDefaults 中,以便我们只能获得收藏夹的 tableview。 (我使用 segmentedControl 作为过滤 where libraryFilter = 0(Plan) / 1 = Tag / 2 = Duration / 3 = Favorite)

jsonErgWorkouts 是来自 JSON 文件的锻炼数组,它是过滤的基础。

这是我编写的代码

自定义 TableViewCell:

import UIKit

class ErgWorkoutCell: UITableViewCell {
  
  @IBOutlet weak var ergWorkoutTitle: UILabel! 
}

在 TableView 视图控制器中

  func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let selectedGroup = selectedWorkoutGroup(libraryFilter: libraryFilter,jsonErgWorkouts: jsonErgWorkouts,workoutGroupBox: workoutGroupBox)
    
    /// this is cast AS! ErgWorkoutCell since this is a custom tableViewCell
    let cell = tableView.dequeueReusableCell(withIdentifier: "ergWorkoutCell") as! ErgWorkoutCell
    
    cell.ergWorkoutTitle.text = selectedGroup[indexPath.row].title
    return cell
  }
}


func selectedWorkoutGroup(libraryFilter: Int,jsonErgWorkouts:[workoutList],workoutGroupBox: UITextField) -> [workoutList] {
  var selectedGroup = [workoutList]()
    
  if libraryFilter == 0 { // Segmented Control #1 (Plan)
    selectedGroup = jsonErgWorkouts.filter { $0.group == workoutGroupBox.text }
  /// code for libraryFilter 1(Tag)
  ///      and libraryFilter 2(Duration) 
  } else if libraryFilter == 3 {
    // Need code here to return the filtered JSON of favorites only
  }
  
  return selectedGroup
}

enter image description here

解决方法

需要做的事情很少。我还将链接一些有助于获得此解决方案的 SO 页面。

  1. 在故事板中添加按钮
  2. 在自定义 TableViewCell 中添加一个按钮定义(IBOutlet/IBAction)和一个闭包
  3. 添加一种将所选收藏夹存储到 UserDefaults 中的方法
  4. 在 segmentedControl 中显示收藏夹列表。

让我们开始吧:

  1. 向情节提要中添加按钮

    我会把这个留给用户

  2. 在自定义 TableViewCell 中添加一个按钮定义(IBOutlet/IBAction)和一个闭包

    import UIKit
    class ErgWorkoutCell: UITableViewCell {
    
      @IBOutlet weak var ergWorkoutTitle: UILabel!
    
      /// Create and Connect your Button outlet
      @IBOutlet weak var ergWorkoutFavBtn: UIButton!
    
      /// create your closure here
      /// https://stackoverflow.com/a/55743790/14414215
      var favButtonPressed : (() -> ()) = {}
    
      /// Create & Connect an IBAction when your button is pressed. 
      @IBAction func ergWorkoutFavBtn(_ sender: UIButton) {
        /// Call your closure here
        favButtonPressed()
      }
    }
    
  3. 添加一种将所选收藏夹存储到 UserDefaults 中的方法

    func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    /// https://stackoverflow.com/a/37357869/14414215
    /// https://stackoverflow.com/q/65355061/14414215
    /// Provide an initial default (empty array) to the UserDefaults Array since on startup there is no fav in the list.
    var rowsWhichAreChecked = UserDefaults.standard.array(forKey: "workoutFavorite") as? [Int] ?? [Int]()
    
    /// this is cast AS! ErgWorkoutCell since this is a custom tableViewCell
    let cell = tableView.dequeueReusableCell(withIdentifier: "ergWorkoutCell") as! ErgWorkoutCell
    
    cell.ergWorkoutTitle.text = selectedGroup[indexPath.row].title
    
    /// This is to change the image between favourited or Not
    if rowsWhichAreChecked.contains(selectedGroup[indexPath.row].id) {
      cell.ergWorkoutFavBtn.setImage(#imageLiteral(resourceName: "star-full"),for: .normal)
    } else {
      cell.ergWorkoutFavBtn.setImage(#imageLiteral(resourceName: "star-empty"),for: .normal)
    }
    
    /// https://stackoverflow.com/a/55743790/14414215
    /// Once the FavButton is pressed,we determine if the selected item is already 
    /// in the FavList. If Yes,we remove it,if Not,we add it in.
    /// We then reload the table
    /// Added [ weak self] in based on @azehe
    /// https://stackoverflow.com/q/64297651/14414215
    cell.favButtonPressed = { [ weak self ] in
      if rowsWhichAreChecked.contains(selectedGroup[indexPath.row].id) {
        let removeIdx = rowsWhichAreChecked.lastIndex(where: {$0 == selectedGroup[indexPath.row].id})
        rowsWhichAreChecked.remove(at: removeIdx!)
    
        cell.ergWorkoutFavBtn.setImage(#imageLiteral(resourceName: "star-empty"),for: .normal)
      } else {
        cell.ergWorkoutFavBtn.setImage(#imageLiteral(resourceName: "star-full"),for: .normal)
        rowsWhichAreChecked.append(selectedGroup[indexPath.row].id)
      }
      UserDefaults.standard.set(rowsWhichAreChecked,forKey: "workoutFavorite")
      self?.vcLibTableView.reloadData() // self? instead of self (with [weak self] in
    }
      return cell
    }
    
  4. 在 segmentedControl 中显示收藏夹列表。

   func selectedWorkoutGroup(libraryFilter: Int,jsonErgWorkouts:[workoutList],workoutGroupBox: UITextField) -> [workoutList] {
     var selectedGroup = [workoutList]()
     
     /// https://stackoverflow.com/a/37357869/14414215
     let workoutFav = UserDefaults.standard.array(forKey: "workoutFavorite") as? [Int] ?? [Int]()

     if libraryFilter == 0 {
       selectedGroup = jsonErgWorkouts.filter { $0.group == workoutGroupBox.text }
     } else if libraryFilter == 1 {
       /// https://stackoverflow.com/q/65355061/14414215
       selectedGroup = workoutFav.flatMap { favouriteId in // for each favourite ID
             jsonErgWorkouts.filter { $0.id == favouriteId }
      } // flatMap joins all those arrays returns by "filter" together,no need to do anything else
     }
     
     return selectedGroup
   }

Result

根据@azehe 评论的输入添加 [weak self] in 。您可以在内存图中看到差异。 Debug Memory Graph differences

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。