ios - 使用 Eureka 表单的内存泄漏问题
问题描述
我正在开发应用程序“密码管理器”。在 RootVC(VC - 视图控制器)中,我有保存密码的表。单击行中的密码,我打开第二个名为 EditPasswordVC 的 VC,其中包含密码详细信息。密码存储在 Core Data (PasswordModel) 中。这是工作,但是当我打开密码时,我的记忆不断增加,看到密码返回后,再次打开相同或另一个密码,我的记忆不断增加。为什么?
根VC:
import UIKit
import CoreData
import SVProgressHUD
class ResponsiveView: UIView {
override var canBecomeFirstResponder: Bool {
return true
}
}
class RootVC: UITableViewController {
var passwordsArray = [PasswordModel]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
@IBOutlet weak var addBarButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
loadPasswords()
SVProgressHUD.dismiss()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return passwordsArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RootCell", for: indexPath)
cell.textLabel?.text = passwordsArray[indexPath.row].title
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let editPasswordVC = EditPasswordVC()
editPasswordVC.passwordData = passwordsArray[indexPath.row]
self.navigationController?.pushViewController(editPasswordVC, animated: true)
}
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .normal, title: "Delete") { (action, sourceView, completionHandler) in
self.createConfirmDeletingAlertMessage(indexPath: indexPath)
}
delete.backgroundColor = .red
delete.image = UIImage(named: "delete-icon")
let swipeAction = UISwipeActionsConfiguration(actions: [delete])
swipeAction.performsFirstActionWithFullSwipe = false // This line disables full swipe
return swipeAction
}
private func loadPasswords() {
let request: NSFetchRequest<PasswordModel> = PasswordModel.fetchRequest()
do {
passwordsArray = try context.fetch(request)
} catch {
print("error load \(error)")
}
self.tableView.reloadData()
}
private func createConfirmDeletingAlertMessage(indexPath: IndexPath) {
let alertVC = UIAlertController(title: "Confirm deleting password!", message: "", preferredStyle: .alert)
let deleteAction = UIAlertAction(title: "DELETE", style: .default, handler: { (saveAction) in
self.deletePassword(indexPath: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
})
let cancelAction = UIAlertAction(title: "CANCEL", style: .default, handler: nil)
alertVC.addAction(deleteAction)
alertVC.addAction(cancelAction)
self.present(alertVC, animated: true, completion: nil)
}
private func deletePassword(indexPath: Int) {
self.context.delete(self.passwordsArray[indexPath])
self.passwordsArray.remove(at: indexPath)
do {
try self.context.save()
} catch {
print("error save in root vc \(error)")
}
}
}
这是 EditPasswordVC:
import Foundation
import Eureka
import GenericPasswordRow
import SVProgressHUD
protocol EditPasswordVCDelegate {
func editDidEnd()
}
class EditPasswordVC: FormViewController {
var passwordData: PasswordModel!
override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent)
if parent == nil{
self.navigationController?.isToolbarHidden = false
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupView()
initElements()
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)
}
private func setupView() {
self.title = "Password detail"
self.navigationController?.isToolbarHidden = true
self.hideKeyboardWhenTappedAround()
navigationOptions = RowNavigationOptions.Disabled
createBarButtonItems()
}
private func createBarButtonItems() {
let editButton = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editButtonPressed))
self.navigationItem.rightBarButtonItem = editButton
}
private func initElements() {
form +++ Section("Password information") {
$0.header?.height = { 40 }
}
<<< CustomTextCellRow() {
$0.tag = RowTags.rowTitleTag.rawValue
}.cellSetup({ (titleCell, titleRow) in
titleCell.setupTitleCell()
titleCell.setupNonEditCell()
titleCell.textFieldCustomTextCell.text = self.passwordData.title
})
<<< WebPageCellRow() {
$0.tag = RowTags.rowWebPageTag.rawValue
}.cellSetup({ (webPageCell, webPageRow) in
webPageCell.setupNonEditCell()
webPageCell.textFieldWebPage.text = self.passwordData.webPage
})
<<< CustomTextCellRow() {
$0.tag = RowTags.rowEmailTag.rawValue
}.cellSetup({ (emailCell, emailRow) in
emailCell.setupEmailCell()
emailCell.setupNonEditCell()
emailCell.textFieldCustomTextCell.text = self.passwordData.email
})
<<< CustomTextCellRow() {
$0.tag = RowTags.rowUsernameTag.rawValue
}.cellSetup({ (usernameCell, usernameRow) in
usernameCell.setupUsernameCell()
usernameCell.setupNonEditCell()
usernameCell.textFieldCustomTextCell.text = self.passwordData.username
})
+++ Section("Enter password") {
$0.header?.height = { 20 }
}
<<< GenericPasswordRow() {
$0.tag = RowTags.rowPasswordTag.rawValue
}.cellSetup({ (passwordCell, passwordRow) in
passwordCell.setupPasswordCell()
passwordCell.setupNonEditRow()
passwordCell.textField.text = self.passwordData.password
passwordCell.updatePasswordStrenghtAndTextFieldDidChange()
})
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let customTextCell = tableView.cellForRow(at: indexPath) as? CustomTextCell {
UIPasteboard.general.string = customTextCell.textFieldCustomTextCell.text
SVProgressHUD.showInfo(withStatus: "Copied To Clipboard")
SVProgressHUD.dismiss(withDelay: 1)
} else if let genericPasswordCell = tableView.cellForRow(at: indexPath) as? GenericPasswordCell {
UIPasteboard.general.string = genericPasswordCell.textField.text
SVProgressHUD.showInfo(withStatus: "Copied To Clipboard")
SVProgressHUD.dismiss(withDelay: 1)
} else {
let webPageCell = tableView.cellForRow(at: indexPath) as? WebPageCell
guard let url = URL(string: webPageCell!.textFieldWebPage.text ?? "https://") else { return }
UIApplication.shared.open(url)
}
tableView.deselectRow(at: indexPath, animated: false)
}
}
这是我的仪器跟踪的链接。我做错了什么?
谢谢
解决方案
使用参数处理程序更改 UIContextualAction 声明将解决内存问题。以下是所需的修改。
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .normal, title: "Delete", handler: { (action, sourceView, completionHandler) in
self.createConfirmDeletingAlertMessage(indexPath: indexPath)
})
delete.backgroundColor = .red
delete.image = UIImage(named: "delete-icon")
let swipeAction = UISwipeActionsConfiguration(actions: [delete])
swipeAction.performsFirstActionWithFullSwipe = false // This line disables full swipe
return swipeAction
}
推荐阅读
- r - 如何在 R 包中的说明中添加参考作者?
- c++ - 为什么我的 C++ 程序的汇编输出充满了没有汇编代码的 .ascii?
- python - 根据实例变量对对象数组进行排序
- azure-media-services - Azure 媒体服务:媒体/视频无法在 Safari/Edge 浏览器上解密,但在 Chrome 中运行良好
- azure-active-directory - 需要用户登录才能使用 Bot Framework 和 AAD OAuth2
- mongodb - 如何不匹配 MongoDB 内元素子数组中的文档
- r - 尝试合并两个不同长度的数据集(在 R 中使用 Combine()
- typescript - TypeScript 对象属性需要重复定义
- scala - 将包含字符串的列转换为包含 Apache Spark UDF 中的对象列表的列
- javascript - 如何对二维数组进行分组并将其转换为具有键名的对象