手动修改系统时间触发Xcode项目安装失败,打卡计数器代码问题咨询
问题解答
一、安装报错原因
这个unable to install xcode project报错和你的业务代码无关,是手动修改设备时间的正常现象。
Xcode向真机安装应用时,会校验应用签名的有效期、生成时间和设备当前时间是否匹配,手动修改设备时间到签名证书生效前、或者过期后的时间区间,就会触发签名校验失败,导致安装失败。将设备时间恢复为自动同步后校验通过,安装即可恢复正常。
二、现有打卡逻辑可优化点
你的核心逻辑整体是通顺的,但存在少量边界场景的问题,可以按需调整:
- 时间回拨的边界处理:当前逻辑仅在时间差大于等于24小时、或小于等于-24小时时才会重置连胜,如果用户手动把时间往回调了几个小时(比如从今天1点拨回昨天23点),时间差为-2小时,此时点击打卡会触发「跨天且小于24小时」的判断,错误给连胜数加1。可以在判断前先增加逻辑:如果当前时间早于上次打卡时间,直接判定为无效打卡即可。
- DateFormatter性能优化:当前每次调用
FormatDate1都会新建一个DateFormatter实例,该类的创建开销较高,建议改为全局/静态属性复用,避免重复创建损耗性能。 - 数据持久化风险:UserDefaults存储的数据会随app卸载被清除,如果需要保留用户连胜数据,后续可以考虑接入iCloud Key-value同步能力。
模拟器测试方法
不需要修改真机时间也可以完成逻辑测试:
- 可以直接修改模拟器的系统时间,和修改真机时间操作一致,不会触发Xcode安装校验问题
- 也可以在代码中临时把
Date()替换为你需要的自定义时间对象,直接测试不同时间差的边界场景
修正后核心逻辑参考代码
let defaults = UserDefaults.standard // 复用DateFormatter private let dateFormatter: DateFormatter = { let df = DateFormatter() df.dateFormat = "dd MMM, yyyy hh:mm:ss" return df }() override func viewDidLoad() { super.viewDidLoad() //User Defaults on first Load if defaults.object(forKey: "lastDate") == nil { defaults.set(Date(), forKey: "lastDate") print("Default 'lastDay' Set for: " + FormatDate1(date: defaults.object(forKey: "lastDate") as! Date)) } //Info print("Current Day is: " + FormatDate1(date: Date())) print("'lastDay' was: " + FormatDate1(date: defaults.object(forKey: "lastDate") as! Date)) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) OneDayApart() } //Button Action @IBAction func buttonAction(_ sender: Any) { let date1 = Date() let date2 = defaults.object(forKey: "lastDate") as! Date let difference = Calendar.current.dateComponents([.hour], from: date2, to: date1) print("The difference In Hours Is: \(difference.hour!)") // 新增:当前时间早于上次打卡时间,直接判定为无效打卡 guard difference.hour! >= 0 else { print("当前时间早于上次打卡时间,打卡无效") return } //If 24 hours+ if difference.hour! >= 24 { print("The difference In Hours Is Greater Than 24 So DayNumber is Reset to 0") defaults.set(Date(), forKey: "lastDate") defaults.set(0, forKey: "DayNumber") //If same day } else if Calendar.current.isDate(date1, inSameDayAs:date2) == true { print("Current Day is: " + FormatDate1(date: Date())) defaults.set(Date(), forKey: "lastDate") print("Same day as before, But 'lastDay' is reset for: " + FormatDate1(date: defaults.object(forKey: "lastDate") as! Date)) print("Streak: " + String(defaults.integer(forKey: "DayNumber"))) //If Different DAY && It's been LESS than 24 Hours } else if Calendar.current.isDate(date1, inSameDayAs:date2) == false && difference.hour! < 24 { print("This is a different day") defaults.set(Date(), forKey: "lastDate") print("The New 'lastDay': " + FormatDate1(date: defaults.object(forKey: "lastDate") as! Date)) let addedNumber = defaults.integer(forKey: "DayNumber") + 1 defaults.set(addedNumber, forKey: "DayNumber") print("Streak: " + String(defaults.integer(forKey: "DayNumber"))) } //Let Label Equal Number streakNumberLabel.text = String(defaults.integer(forKey: "DayNumber")) } //FORMATS DATE func FormatDate1(date : Date) -> String { return dateFormatter.string(from: date) } //Check if it has been 24 Hours+ and Let Label Equal Number func OneDayApart() { let date1 = Date() //today let date2 = defaults.object(forKey: "lastDate") as! Date //last day let difference = Calendar.current.dateComponents([.hour], from: date2, to: date1) print("The difference In Hours Is: \(difference.hour!)") //HAS IT BEEN MORE THAN 24 HOURS? if difference.hour! >= 24 { print("The difference In Hours Is Greater Than 24 So DayNumber is Reset to 0") defaults.set(0, forKey: "DayNumber") } //Let Label Equal Number streakNumberLabel.text = String(defaults.integer(forKey: "DayNumber")) }
内容的提问来源于stack exchange,提问作者Rem Biths Wind
相关产品推荐
相关产品推荐

