如何在iOS应用中以编程方式集成Realm数据库?
集成Realm解决iOS应用数据持久化问题
问题背景
我开发了一款iOS应用,需要在Realm数据库中存储标题(Title)和图片(或图片路径)两个字段。目前数据存储在Video结构体中,但重启应用后所有修改都会丢失。需要将现有代码改造为集成Realm的版本,实现数据持久化。
现有代码如下:
struct Video { var image: UIImage var title : String } class VideoCell: UITableViewCell { var videoImageView=UIImageView() var videoTitleLabel=UILabel() required init?(coder:NSCoder){ fatalError("init(coder:) has not been implemented") } func set(video : Video) { videoTitleLabel.text = video.title videoImageView.image = video.image } } class VideoListVC: UIViewController, UISearchResultsUpdating { var tableView=UITableView() var videos : [Video] = [] var videoImageView=UIImageView() var videoTitleLabel=UILabel() struct Cells { static let videoCell = "VideoCell" } override func viewDidLoad(){ super.viewDidLoad() title = "" videos = fetchData() configureTableView() } func configureTableView(){ view.addSubview(tableView) setTableViewDelegates() tableView.rowHeight = 290 tableView.register(VideoCell.self, forCellReuseIdentifier: Cells.videoCell) tableView.pin(to:view) } func setTableViewDelegates(){ tableView.delegate=self tableView.dataSource=self } } extension VideoListVC: UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return videos.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: Cells.videoCell) as! VideoCell let video = videos[indexPath.row] cell.set(video: video) return cell } func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { return .delete } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { tableView.beginUpdates() videos.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) tableView.endUpdates() } } }
集成Realm的步骤
1. 安装Realm
通过CocoaPods安装,在项目的Podfile中添加:
pod 'RealmSwift'
执行pod install命令后,使用.xcworkspace文件打开项目。
2. 将Video结构体改为Realm模型
Realm要求数据模型必须继承自Object,且无法直接存储UIImage类型,推荐两种存储方案:
方案一:存储图片本地路径(推荐,避免数据库体积过大)
import RealmSwift class Video: Object { @Persisted var title: String = "" @Persisted var imagePath: String = "" // 存储图片在沙盒中的路径 // 从路径加载UIImage的计算属性 var image: UIImage? { guard !imagePath.isEmpty else { return nil } let url = URL(fileURLWithPath: imagePath) guard let data = try? Data(contentsOf: url) else { return nil } return UIImage(data: data) } }
方案二:存储图片Data(适合小体积图片)
import RealmSwift class Video: Object { @Persisted var title: String = "" @Persisted var imageData: Data? // 存储图片的二进制数据 // 从Data转UIImage的计算属性 var image: UIImage? { guard let data = imageData else { return nil } return UIImage(data: data) } }
3. 修改数据操作逻辑
替换原有内存级数据操作,改为Realm持久化操作:
import RealmSwift class VideoListVC: UIViewController, UISearchResultsUpdating { var tableView=UITableView() var videos: Results<Video>! // 使用Realm的Results类型,自动监听数据变化 private let realm = try! Realm() // 获取Realm数据库实例 // ... 保留原有UI配置代码 ... override func viewDidLoad(){ super.viewDidLoad() title = "" fetchData() configureTableView() // 监听Realm数据变化,自动刷新表格 NotificationCenter.default.addObserver(self, selector: #selector(realmDataChanged), name: NSNotification.Name.RealmDidChange, object: realm) } deinit { NotificationCenter.default.removeObserver(self) } @objc private func realmDataChanged() { tableView.reloadData() } func fetchData() { // 查询所有Video数据,Results会自动实时更新 videos = realm.objects(Video.self) } // 新增:保存Video数据到Realm func saveVideo(title: String, image: UIImage) { let video = Video() video.title = title // 方案一:保存图片到沙盒并记录路径 if let imageData = image.jpegData(compressionQuality: 0.8) { let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let imageName = UUID().uuidString + ".jpg" let imageURL = documentsDir.appendingPathComponent(imageName) try? imageData.write(to: imageURL) video.imagePath = imageURL.path } // 方案二:直接存储图片Data // video.imageData = image.jpegData(compressionQuality: 0.8) // 写入Realm必须在事务中执行 try! realm.write { realm.add(video) } } // 修改删除逻辑:同步删除Realm中的数据 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { let targetVideo = videos[indexPath.row] try! realm.write { realm.delete(targetVideo) // 方案一需同步删除本地图片文件 if !targetVideo.imagePath.isEmpty { try? FileManager.default.removeItem(atPath: targetVideo.imagePath) } } tableView.deleteRows(at: [indexPath], with: .fade) } } }
4. 更新Cell配置方法
适配Realm版Video模型,修改VideoCell的set方法:
class VideoCell: UITableViewCell { // ... 保留原有UI组件代码 ... func set(video: Video) { videoTitleLabel.text = video.title videoImageView.image = video.image } }
5. 关键注意事项
- Realm会自动创建数据库文件,可通过
print(Realm.Configuration.defaultConfiguration.fileURL)查看文件路径。 - 所有添加、删除、修改数据的操作必须放在
realm.write事务中执行。 Results类型自带实时数据监听,配合Realm通知可实现UI自动刷新。- 优先选择存储图片路径的方案,避免数据库体积膨胀影响应用性能。
内容的提问来源于stack exchange,提问作者Captain Grimm
相关产品推荐
相关产品推荐

