You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MyQRCode/docs/COREDATA_INTEGRATION_README.md

9.2 KiB

Core Data 集成说明

🎯 概述

成功将历史记录功能从 SwiftData 迁移到 Core Data这是 Apple 的成熟数据持久化框架,支持 iOS 15 及以上版本,提供更好的兼容性和稳定性。

🔄 迁移内容

1. 数据模型变更

迁移前 (SwiftData)

@Model
final class HistoryItem {
    @Attribute(.unique) var id: UUID
    var content: String
    var dataType: DataType
    var dataSource: DataSource
    var createdAt: Date
    var isFavorite: Bool
    // ... 其他属性
}

迁移后 (Core Data)

<entity name="HistoryItem" representedClassName="HistoryItem" syncable="YES" codeGenerationType="class">
    <attribute name="barcodeType" optional="YES" attributeType="String"/>
    <attribute name="content" optional="YES" attributeType="String"/>
    <attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
    <attribute name="dataSource" optional="YES" attributeType="String"/>
    <attribute name="dataType" optional="YES" attributeType="String"/>
    <attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
    <attribute name="isFavorite" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
    <attribute name="parsedData" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" customClassName="ParsedQRData"/>
    <attribute name="qrCodeType" optional="YES" attributeType="String"/>
</entity>

2. 数据管理器变更

迁移前 (SwiftData)

@MainActor
class HistoryManager: ObservableObject {
    @Published var historyItems: [HistoryItem] = []
    private let modelContext: ModelContext
    
    private func saveHistory() {
        try modelContext.save()
    }
}

迁移后 (Core Data)

class CoreDataManager: ObservableObject {
    static let shared = CoreDataManager()
    let container: NSPersistentContainer
    
    func save() {
        let context = container.viewContext
        if context.hasChanges {
            try context.save()
        }
    }
}

3. 视图层变更

迁移前

struct HistoryView: View {
    @Environment(\.modelContext) private var modelContext
    @Query(sort: \HistoryItem.createdAt, order: .reverse) private var allHistoryItems: [HistoryItem]
}

迁移后

struct HistoryView: View {
    @StateObject private var coreDataManager = CoreDataManager.shared
    
    var filteredItems: [HistoryItem] {
        let allItems = coreDataManager.fetchHistoryItems()
        // ... 过滤逻辑
    }
}

🚀 Core Data 的优势

1. 兼容性

  • 版本支持: iOS 15.0+ 完全支持
  • 稳定性: 经过多年验证的成熟框架
  • 向后兼容: 支持旧版本 iOS 系统

2. 性能优化

  • 内存管理: 高效的懒加载和内存管理
  • 批量操作: 支持批量插入、更新、删除
  • 查询优化: 支持复杂的查询和排序

3. 功能丰富

  • 关系支持: 支持一对一、一对多、多对多关系
  • 数据迁移: 支持数据模型版本迁移
  • 事务支持: 支持 ACID 事务
  • 并发控制: 支持多线程安全操作

4. 开发体验

  • Xcode 集成: 内置数据模型编辑器
  • 调试工具: 丰富的调试和性能分析工具
  • 文档完善: 详细的官方文档和示例

🔧 技术实现细节

1. 数据模型配置

<!-- MyQrCode.xcdatamodeld -->
<entity name="HistoryItem" representedClassName="HistoryItem" syncable="YES" codeGenerationType="class">
    <attribute name="content" optional="YES" attributeType="String"/>
    <attribute name="dataType" optional="YES" attributeType="String"/>
    <attribute name="dataSource" optional="YES" attributeType="String"/>
    <attribute name="createdAt" optional="YES" attributeType="Date"/>
    <attribute name="isFavorite" optional="YES" attributeType="Boolean"/>
    <attribute name="barcodeType" optional="YES" attributeType="String"/>
    <attribute name="qrCodeType" optional="YES" attributeType="String"/>
    <attribute name="parsedData" optional="YES" attributeType="Transformable"/>
</entity>

2. 数据管理器

class CoreDataManager: ObservableObject {
    static let shared = CoreDataManager()
    let container: NSPersistentContainer
    
    init() {
        container = NSPersistentContainer(name: "MyQrCode")
        container.loadPersistentStores { description, error in
            if let error = error {
                print("Core Data 加载失败: \(error.localizedDescription)")
            }
        }
        
        // 启用自动合并更改
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    }
}

3. 数据操作

// 获取数据
func fetchHistoryItems() -> [HistoryItem] {
    let request: NSFetchRequest<HistoryItem> = HistoryItem.fetchRequest()
    request.sortDescriptors = [NSSortDescriptor(keyPath: \HistoryItem.createdAt, ascending: false)]
    
    do {
        return try container.viewContext.fetch(request)
    } catch {
        print("获取历史记录失败: \(error.localizedDescription)")
        return []
    }
}

// 插入数据
func addHistoryItem(_ item: HistoryItem) {
    container.viewContext.insert(item)
    save()
}

// 删除数据
func deleteHistoryItem(_ item: HistoryItem) {
    container.viewContext.delete(item)
    save()
}

// 保存更改
func save() {
    let context = container.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            print("保存失败: \(error.localizedDescription)")
        }
    }
}

4. 搜索和过滤

func searchHistoryItems(query: String) -> [HistoryItem] {
    let request: NSFetchRequest<HistoryItem> = HistoryItem.fetchRequest()
    
    if !query.isEmpty {
        let contentPredicate = NSPredicate(format: "content CONTAINS[cd] %@", query)
        let barcodeTypePredicate = NSPredicate(format: "barcodeType CONTAINS[cd] %@", query)
        let qrCodeTypePredicate = NSPredicate(format: "qrCodeType CONTAINS[cd] %@", query)
        
        let compoundPredicate = NSCompoundPredicate(
            orPredicateWithSubpredicates: [
                contentPredicate,
                barcodeTypePredicate,
                qrCodeTypePredicate
            ]
        )
        
        request.predicate = compoundPredicate
    }
    
    request.sortDescriptors = [NSSortDescriptor(keyPath: \HistoryItem.createdAt, ascending: false)]
    
    do {
        return try container.viewContext.fetch(request)
    } catch {
        print("搜索历史记录失败: \(error.localizedDescription)")
        return []
    }
}

📱 用户界面更新

1. 历史记录页面

  • 使用 CoreDataManager 获取和管理数据
  • 支持实时搜索和过滤
  • 数据变更立即反映到 UI

2. 创建页面

  • 使用 Core Data 上下文创建新记录
  • 自动保存和错误处理
  • 支持事务回滚

3. 数据管理

  • 支持批量删除和清空
  • 收藏状态实时同步
  • 完整的错误处理

🧪 测试要点

1. 功能测试

  • 历史记录正确保存和加载
  • 搜索和过滤功能正常
  • 收藏状态正确切换
  • 删除和清空功能正常

2. 性能测试

  • 大量数据加载性能
  • 搜索响应速度
  • 内存使用情况

3. 兼容性测试

  • iOS 15.0+ 设备正常工作
  • 数据迁移和版本兼容性

🚨 注意事项

1. 版本要求

  • 最低版本: iOS 15.0+
  • 推荐版本: iOS 15.0 或更高
  • 优势: 比 SwiftData 支持更广泛的 iOS 版本

2. 数据迁移

  • 支持数据模型版本迁移
  • 建议实现数据迁移策略
  • 考虑数据备份和恢复

3. 性能考虑

  • 大量数据时考虑分页加载
  • 复杂查询时使用适当的索引
  • 定期清理过期数据

📊 迁移效果对比

特性 SwiftData Core Data
版本支持 iOS 17.0+ iOS 15.0+
性能 优秀 优秀
类型安全 中等
功能丰富度 丰富 非常丰富
开发体验 优秀 优秀
稳定性 新框架 成熟稳定
文档支持 有限 完善
社区支持 成熟

🔮 未来扩展

1. 数据关系

  • 支持二维码和条形码的分类标签
  • 支持用户自定义分组
  • 支持数据导入/导出

2. 云同步

  • 支持 iCloud 同步
  • 支持多设备数据同步
  • 支持数据备份和恢复

3. 高级功能

  • 支持数据分析和统计
  • 支持智能搜索和推荐
  • 支持数据压缩和优化

📝 总结

通过这次迁移,我们成功将历史记录功能升级到 Core Data

  1. 兼容性提升: 支持 iOS 15.0+ 的广泛版本范围
  2. 稳定性增强: 使用经过验证的成熟框架
  3. 功能丰富: 支持复杂查询、关系、事务等高级功能
  4. 开发体验: 完善的工具链和文档支持
  5. 未来扩展: 为后续功能扩展奠定坚实基础

Core Data 的集成标志着应用数据层的重要升级,为用户提供更稳定、更可靠的体验,同时保持了广泛的设备兼容性。🎉