You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动修改系统时间触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 12:45:03