使用自定义 UITableViewCell 添加到收藏夹到 UIButton 并保存到 UserDefaults
Posted
技术标签:
【中文标题】使用自定义 UITableViewCell 添加到收藏夹到 UIButton 并保存到 UserDefaults【英文标题】:Add to Favorite using Custom TableViewCell via UIButton & Save to UserDefaults 【发布时间】:2020-12-19 03:37:23 【问题描述】:目标:在自定义 TableViewCell 中创建一个“添加到收藏夹”按钮,然后将收藏夹列表保存到 UserDefaults 中,这样我们就可以只获得收藏夹的表格视图。 (我使用 segmentedControl 作为过滤 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
【问题讨论】:
你有几个无法解释的变量。 【参考方案1】:需要做的事情很少。我还将链接一些有助于获得此解决方案的 SO 页面。
-
在情节提要中添加一个按钮
在自定义 TableViewCell 中添加一个按钮定义(IBOutlet/IBAction)和一个闭包
添加将所选收藏夹存储到 UserDefaults 中的方法
在 segmentedControl 中显示收藏夹列表。
让我们开始吧:
在情节提要中添加一个按钮
我会把这个留给用户
在自定义 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://***.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()
添加一种将所选收藏夹存储到 UserDefaults 中的方法
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
/// https://***.com/a/37357869/14414215
/// https://***.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://***.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://***.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
在 segmentedControl 中显示收藏夹列表。
func selectedWorkoutGroup(libraryFilter: Int, jsonErgWorkouts:[workoutList], workoutGroupBox: UITextField) -> [workoutList]
var selectedGroup = [workoutList]()
/// https://***.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://***.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
根据@azehe 评论的输入添加[weak self] in
。您可以在内存图中看到差异。
【讨论】:
您可能需要在cell.favButtonPressed =
内添加一个[weak self]
@aheze 你能详细说明一下吗?我是 Swift 初学者,即使在阅读 donnywals.com/when-to-use-weak-self-and-why 之后,我也不知道如何/为什么要使用它,我也尝试输入 cell.favButtonPressed = [weak self]
,但它导致了错误/。谢谢。
您还需要一个in
、cell.favButtonPressed = [weak self] in
所以在favButtonPressed
中,您正在捕获self.vcLibTableView.reloadData()
中的self
实例。我对闭包不太擅长,但我问了question 这可能对你有帮助
@azehe 谢谢!!我认为这有所作为。我尝试了内存图的东西,可以看到很大的不同。以上是关于使用自定义 UITableViewCell 添加到收藏夹到 UIButton 并保存到 UserDefaults的主要内容,如果未能解决你的问题,请参考以下文章
如何将子视图添加到情节提要中的自定义 UITableViewCell
UIButton 在自定义 UITableviewCell 中没有响应
Swift 中的自定义 UITableViewCell 注册类