// // DatabaseHelper.swift // MTP2_iOS // // Created by zhongyuan on 2018/6/9. // Copyright © 2018年 zhongyuan.All rights reserved. // import UIKit import CoreData enum DataBaseError: Error { case NoFindUser case NoFindSelfGoods } /// Database Helper class DatabaseHelper { static let appDelegate = UIApplication.shared.delegate as! AppDelegate // MARK: - 生命周期相关 static func firstOpenInitialData() { // 判断是否第一次运行 if !UserDefaultsUtils.isFirstOpen() { return } // 初始化可能与登录相关的错误码 var errorCodeInfos = [MoErrorCodeInfo]() errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1003", errorMsg: "账号或密码不匹配")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1004", errorMsg: "无效账号")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1005", errorMsg: "账号类型不匹配")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1006", errorMsg: "账号不在线")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1007", errorMsg: "操作权限不够")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1008", errorMsg: "会员无账户在线")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1009", errorMsg: "账户在别处登录")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1010", errorMsg: "值为空")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1011", errorMsg: "登录账户已经存在")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1012", errorMsg: "软件版本过低不能登录")) errorCodeInfos.append(MoErrorCodeInfo(errorCode: "1013", errorMsg: "IP地址不在允许范围内")) try? updateErrorCodeInfos(errorCodeInfos: errorCodeInfos) } // MARK: - 账户相关 /// 获取指定用户id的本地用户信息对象 /// /// - Parameter userID: 用户id /// - Returns: 用户信息对象 static func getUser(userID: UInt32) throws -> UserEntity? { let fetchRequest: NSFetchRequest = UserEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "userID == %ld", userID) let result = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) return result.count != 0 ? result[0] : nil } static func getUser(userID: UInt32, type: Int16) throws -> UserEntity? { let fetchRequest: NSFetchRequest = UserEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "userID == %ld and type == %ld", userID,type) let result = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) return result.count != 0 ? result[0] : nil } /// 获取所有保存的用户信息 /// /// - Parameter type: 类型,0为实盘(默认值);1为模拟盘 /// - Returns: 用户信息数组 /// - Throws: 数据库操作错误 static func getUsers(type: Int16 = 0) throws -> [UserEntity]? { let fetchRequest: NSFetchRequest = UserEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "type == %ld", type) fetchRequest.sortDescriptors = [NSSortDescriptor(key: "loginDate", ascending: false)] let result = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) return result.count != 0 ? result : nil } /// - Parameters: /// - userID: 用户id /// - loginID: 登录id /// - type: 类型,0为实盘(默认值);1为模拟盘 /// - Throws: 数据库操作错误 static func addUser(userID: UInt32, loginID: String, loginDate: Date, type: Int16 = 0) throws { if let userEntity = try getUser(userID: userID, type: type) { userEntity.loginDate = loginDate } else { guard let userEntity = NSEntityDescription.insertNewObject(forEntityName: "UserEntity", into: appDelegate.backGroundObjectContext) as? UserEntity else { return } userEntity.userID = Int64(Int32(userID)) userEntity.loginID = loginID userEntity.loginDate = loginDate userEntity.type = type } appDelegate.backGroundObjectContext.perform { if appDelegate.backGroundObjectContext.hasChanges { try? appDelegate.backGroundObjectContext.save() } } } static func deleteUser(userID: UInt32) throws { do { if let userEntity = try getUser(userID: userID) { appDelegate.backGroundObjectContext.perform { appDelegate.backGroundObjectContext.delete(appDelegate.backGroundObjectContext.object(with: userEntity.objectID)) if appDelegate.backGroundObjectContext.hasChanges { try? appDelegate.backGroundObjectContext.save() } } } } catch { throw DataBaseError.NoFindUser } } // MARK: - 错误码相关 static func updateErrorCodeInfos(errorCodeInfos: [MoErrorCodeInfo]) throws { func deleteAllErrorCodeInfos() throws { let fetchRequest = NSFetchRequest(entityName: "ErrorEntity") let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) try appDelegate.backGroundObjectContext.execute(batchDeleteRequest) } if errorCodeInfos.count <= 0 { return } // 批量删除原有数据 try deleteAllErrorCodeInfos() appDelegate.backGroundObjectContext.perform { for moErrorCodeInfo in errorCodeInfos { // FIXME: 可能会报 EXC_BAD_ACCESS guard let errorEntity = NSEntityDescription.insertNewObject(forEntityName: "ErrorEntity", into: appDelegate.backGroundObjectContext) as? ErrorEntity else { return } errorEntity.constkey = moErrorCodeInfo.errorCode errorEntity.remarks = moErrorCodeInfo.errorMsg } if appDelegate.backGroundObjectContext.hasChanges { try? appDelegate.backGroundObjectContext.save() } } } static func getError(errorCode: String) throws -> ErrorEntity? { let fetchRequest: NSFetchRequest = ErrorEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "constkey == %@", errorCode) let result = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) return result.count != 0 ? result[0] : nil } // MARK: - 自选商品相关 static func getSelfQuotes(userID: UInt32) throws -> [SelfEntity] { if let userEntity = try getUser(userID: userID) { if let selfGoods = userEntity.selfGoods?.allObjects as? [SelfEntity] { return selfGoods } } return [] } static func addSelfGoods(userID: UInt32, goodsID: Int64, marketID: Int64) throws { if let userEntity = try getUser(userID: userID) { guard let selfEntity = NSEntityDescription.insertNewObject(forEntityName: "SelfEntity", into: appDelegate.backGroundObjectContext) as? SelfEntity else { return } appDelegate.backGroundObjectContext.perform { selfEntity.goodsID = goodsID selfEntity.marketID = marketID selfEntity.createTime = NSDate() let userEntity: UserEntity = appDelegate.backGroundObjectContext.object(with: userEntity.objectID) as! UserEntity userEntity.addToSelfGoods(selfEntity) if appDelegate.backGroundObjectContext.hasChanges { do { try appDelegate.backGroundObjectContext.save() } catch { dPrint(error.localizedDescription) } } } } else { throw DataBaseError.NoFindUser } } static func removeSelfGoods(userID: UInt32, goodsID: Int64) throws { if let userEntity = try getUser(userID: userID) { if case let selfEntity as SelfEntity = userEntity.selfGoods?.first(where: { ($0 as! SelfEntity).goodsID == goodsID }) { appDelegate.backGroundObjectContext.perform { userEntity.removeFromSelfGoods(selfEntity) appDelegate.backGroundObjectContext.delete(appDelegate.backGroundObjectContext.object(with: selfEntity.objectID)) // 这一句记得要调用 if appDelegate.backGroundObjectContext.hasChanges { try? appDelegate.backGroundObjectContext.save() } } } else { throw DataBaseError.NoFindSelfGoods } } else { throw DataBaseError.NoFindUser } } //MARK: - 商品相关 static func insertGoodsInfos(_ goodsInfos: [MoGoodsInfo]) throws { /// 先移出商品 do { for goods in goodsInfos { let exist = try? self.getGoodsInfo(ById: goods.goodsid) if exist ?? false { self.removeGoodsInfo(goods.goodsid) } } } appDelegate.backGroundObjectContext.performAndWait { do { dPrint("1.当前时间:\(Date().getString())") for goodsInfo in goodsInfos { guard let goodsInfoEntity = NSEntityDescription.insertNewObject(forEntityName: "GoodsInfoEntity", into: appDelegate.backGroundObjectContext) as? GoodsInfoEntity else { continue } goodsInfoEntity.setupWith(goodsInfo: goodsInfo) } dPrint("2.当前时间:\(Date().getString())") if appDelegate.backGroundObjectContext.hasChanges { dPrint("3.当前时间:\(Date().getString())") try appDelegate.backGroundObjectContext.save() dPrint("4.当前时间:\(Date().getString())") } else { dPrint("商品本地化失败") } } catch { fatalError("商品数据插入失败") } } } /// 判断指定商品信息是否存在 /// /// - Parameter Id: 商品ID /// - Returns: yes: 存在 no: 不存在 /// - Throws: static func getGoodsInfo(ById Id: Int) throws -> Bool { let fetchRequest: NSFetchRequest = GoodsInfoEntity.fetchRequest() fetchRequest.predicate = NSPredicate(format: "goodsId == %ld", Int32(Id)) let count = try appDelegate.mainManagedObjectContext.count(for: fetchRequest) return count > 0 } /// 获取所有商品信息 /// /// - Returns: 所有保存的商品信息 /// - Throws: static func getGoodsInfo() throws -> [MoGoodsInfo] { let fetchRequest: NSFetchRequest = GoodsInfoEntity.fetchRequest() fetchRequest.sortDescriptors = [NSSortDescriptor(key: "goodsCode", ascending: true)] let goodsInfos = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) let moGoodsInfos = goodsInfos.compactMap({ $0.toMoGoodsInfo() }) return moGoodsInfos } /// 判断本地数据库是否有数据 /// /// - Returns: yes: 存在 no: 不存在 /// - Throws: static func goodsInfoIsExist() -> Bool { let fetchRequest: NSFetchRequest = GoodsInfoEntity.fetchRequest() do { let count = try appDelegate.mainManagedObjectContext.count(for: fetchRequest) return count > 0 } catch { fatalError() } } /// 根据查询条件获取符合条件的商品 /// /// - Parameter searchCondition: 查询条件 /// - Returns: 符合条件的商品 /// - Throws: static func getGoodsInfo(ByCondition searchCondition: String) throws -> [MoGoodsInfo] { guard !searchCondition.isEmpty else { return [] } let fetchRequest: NSFetchRequest = GoodsInfoEntity.fetchRequest() if RegularUtils.checkNumber(with: searchCondition) { let regularString = ".*\(searchCondition).*" fetchRequest.predicate = NSPredicate(format: "searchCondition MATCHES %@", regularString) } else { var regularString = ".*" for s in searchCondition.uppercased() { regularString.append(s) regularString.append(".*") } fetchRequest.predicate = NSPredicate(format: "searchCondition MATCHES %@", regularString) } fetchRequest.sortDescriptors = [NSSortDescriptor(key: "goodsCode", ascending: true)] let goodsInfos = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) let moGoodsInfos = goodsInfos.compactMap({ $0.toMoGoodsInfo() }) return moGoodsInfos } /// 删除所有的商品数据信息 static func removeAllGoodsInfo() { /// 获取上下文对象 let viewContext = appDelegate.persistentContainer.viewContext /// 获取实例 let entity = NSFetchRequest(entityName: "GoodsInfoEntity") let deleteRequest = NSBatchDeleteRequest(fetchRequest: entity) let _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext) appDelegate.backGroundObjectContext.perform { if appDelegate.backGroundObjectContext.hasChanges { do { _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext) } } } } /// 删除所有的商品数据信息 static func removeGoodsInfo(_ goodsid: Int) { /// 获取上下文对象 let viewContext = appDelegate.persistentContainer.viewContext /// 获取实例 let fetchRequest = NSFetchRequest(entityName: "GoodsInfoEntity") fetchRequest.predicate = NSPredicate(format: "goodsId == %ld", Int64(goodsid)) let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) let _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext) appDelegate.backGroundObjectContext.perform { if appDelegate.backGroundObjectContext.hasChanges { do { _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext) } } } } /// 根据goodsid获取对应的商品数据 /// - Parameter goodsid: goodsid static func getMoGoodsInfo(where goodsids: [Int]) throws -> [MoGoodsInfo]? { /// 获取商品数据 var goodsInfo: [MoGoodsInfo] = [] let fetchRequest: NSFetchRequest = GoodsInfoEntity.fetchRequest() for goodsid in goodsids { fetchRequest.predicate = NSPredicate(format: "goodsId == %ld", Int64(goodsid)) let goodsInfos = try appDelegate.mainManagedObjectContext.fetch(fetchRequest) if goodsInfos.count != 0 { goodsInfo.append(goodsInfos[0].toMoGoodsInfo()) } } return goodsInfo } }