点击ViewController按钮向另一控制器UITableView添加名片数据并永久存储
嘿,刚好我之前做过类似的名片扫描保存需求,给你一步步拆解实现方案,保证能搞定:
实现步骤拆解
1. 先把扫描信息结构化:定义名片数据模型
OCR扫出来的都是零散的字符串,咱们得把它们打包成一个清晰的模型,方便后续存储和展示。用struct就够了,加上Codable协议还能直接序列化存到本地:
struct BusinessCard: Codable { let name: String let address: String? // 允许空值,毕竟有些名片可能没写地址 let phoneNumber: String? let email: String? // 写个初始化方法,直接把OCR返回的字典转成模型 init(ocrResult: [String: String]) { self.name = ocrResult["name"] ?? "" self.address = ocrResult["address"] self.phoneNumber = ocrResult["phoneNumber"] self.email = ocrResult["email"] } }
2. 搞定永久存储:实现数据持久化逻辑
要让数据重启APP也不丢,最简单的用UserDefaults(适合名片数量不多的场景),如果之后要存几百上千张,再换成Core Data或者Realm就行。咱们整个单例工具类来管理存储,方便全局调用:
class CardStorage { static let shared = CardStorage() // 单例,全局唯一实例 private let userDefaults = UserDefaults.standard private let storageKey = "SavedBusinessCards" // 存数据的key // 保存整个名片数组 func saveCards(_ cards: [BusinessCard]) { do { let encodedData = try JSONEncoder().encode(cards) userDefaults.set(encodedData, forKey: storageKey) } catch { print("名片保存失败:\(error.localizedDescription)") } } // 获取所有已保存的名片 func getSavedCards() -> [BusinessCard] { guard let savedData = userDefaults.data(forKey: storageKey) else { return [] } do { return try JSONDecoder().decode([BusinessCard].self, from: savedData) } catch { print("读取名片失败:\(error.localizedDescription)") return [] } } // 追加新名片到已有数据里 func addNewCard(_ card: BusinessCard) { var existingCards = getSavedCards() existingCards.append(card) saveCards(existingCards) } }
3. 扫描完成后:保存并跳转/刷新列表
假设你已经完成了OCR扫描,拿到了姓名、地址这些信息,点击保存按钮的时候这么做:
// 这里替换成你真实的OCR扫描结果 let ocrScanResult = [ "name": "张三", "address": "北京市朝阳区XX大厦15层", "phoneNumber": "138XXXX1234", "email": "zhangsan@example.com" ] // 转成模型 let newBusinessCard = BusinessCard(ocrResult: ocrScanResult) // 保存到本地 CardStorage.shared.addNewCard(newBusinessCard) // 跳转到第二个ViewController(如果是用storyboard的话,记得给VC设好identifier) if let secondVC = storyboard?.instantiateViewController(withIdentifier: "CardListVC") as? SecondViewController { navigationController?.pushViewController(secondVC, animated: true) }
4. 第二个VC的TableView配置:展示所有名片
在第二个ViewController里,咱们要做的就是每次进入页面时读取最新数据,然后刷新TableView:
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var cardTableView: UITableView! private var savedCards: [BusinessCard] = [] override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 每次进入页面都拉取最新的名片数据 savedCards = CardStorage.shared.getSavedCards() cardTableView.reloadData() } // MARK: - UITableView数据源方法 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return savedCards.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 记得在storyboard里给cell设好identifier为"CardCell" let cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) let currentCard = savedCards[indexPath.row] // 配置cell内容,这里用默认cell的文本标签举例,你也可以自定义cell显示更多信息 cell.textLabel?.text = currentCard.name cell.detailTextLabel?.text = currentCard.phoneNumber ?? currentCard.email ?? "无联系方式" return cell } // 可以自定义cell高度,让内容显示更舒服 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 80 } }
几个额外的小提示
- 一定要在storyboard里给TableView的cell设置正确的
identifier,不然会崩溃 - 建议在保存前加个编辑页面,让用户核对OCR识别的信息(毕竟OCR偶尔会出错)
- 如果之后名片数量暴涨,
UserDefaults就不够高效了,这时候只需要替换CardStorage里的存储逻辑(换成Core Data),上层的展示代码完全不用改,很灵活
内容的提问来源于stack exchange,提问作者Snehal
相关产品推荐
相关产品推荐

