Swift中如何将字符串数组保存到Realm并在TableView展示
解决方案:将字符串数组保存到Realm并在TableView展示
Realm不支持直接存储原生[String]类型,需要通过**List<Object>包裹自定义模型**的方式来适配,以下是具体实现步骤:
1. 创建单个字符串的Realm模型
首先定义一个封装单个字符串的Object子类,用来作为List的元素类型:
import RealmSwift class StringItem: Object, Decodable { @objc dynamic var value: String = "" // 便捷初始化方法 convenience init(value: String) { self.init() self.value = value } // 解码时直接将字符串转为StringItem required init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let stringValue = try container.decode(String.self) self.init(value: stringValue) } }
2. 修改MessageModel适配Realm
将原有的[String]替换为List<StringItem>,并实现Decodable协议处理服务器返回的数组:
import RealmSwift class MessageModel: Object, Decodable { let result = List<StringItem>() // 解码服务器返回的[String]并转为List<StringItem> required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let stringArray = try container.decode([String].self, forKey: .result) super.init() result.append(objectsIn: stringArray.map { StringItem(value: $0) }) } // Realm必须的空初始化方法 required override init() { super.init() } enum CodingKeys: String, CodingKey { case result } }
3. 修改ViewController实现数据持久化与展示
将数据源替换为Realm的Results(实时更新的查询结果),并通过通知监听数据变化自动刷新TableView:
import UIKit import RealmSwift final class StartController: UIViewController { // 使用Realm Results作为数据源,支持实时更新 private var messageResults: Results<StringItem>? // 监听数据变化的通知令牌 private var notificationToken: NotificationToken? override func viewDidLoad() { super.viewDidLoad() setUpView() setUpConstraints() configData() setupRealmObserver() } private func configData() { service.addMessage(offset: offsetStart) { [weak self] result in switch result { case .success(let dataMessage): // 将服务器数据保存到Realm do { let realm = try Realm() try realm.write { // 可选:清空旧数据再添加新数据,或者直接追加 realm.delete(realm.objects(StringItem.self)) let items = dataMessage.map { StringItem(value: $0) } realm.add(items) } } catch { print("Realm保存失败: \(error)") } case .failure(let error): print(error) DispatchQueue.main.async { self?.showAlert(title: "Error", message: "Error connecting to the server") } } } } // 设置Realm数据监听,自动刷新TableView private func setupRealmObserver() { let realm = try! Realm() messageResults = realm.objects(StringItem.self) notificationToken = messageResults?.observe { [weak self] _ in DispatchQueue.main.async { self?.messageTable.reloadData() } } } // 页面销毁时移除监听 deinit { notificationToken?.invalidate() } // MARK: - TableView DataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messageResults?.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = messageTable.dequeueReusableCell(withIdentifier: identifier, for: indexPath) cell.backgroundColor = UIColor(named: "backgroundColor") guard let messageItem = messageResults?[indexPath.row] else { return cell } var content = cell.defaultContentConfiguration() content.text = messageItem.value return cell } }
关键说明
- Realm仅支持存储
Object子类或其包裹的List,因此必须用StringItem封装单个字符串。 - 使用
Results作为数据源可以自动同步Realm中的数据变化,配合NotificationToken无需手动调用reloadData。 - 所有Realm的写入操作必须在
write事务中执行,确保线程安全。
内容的提问来源于stack exchange,提问作者kovalmark
相关产品推荐
相关产品推荐

