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

如何在Swift中生成限时二维码

如何在Swift中生成限时有效的二维码

首先得明确一个关键点:二维码本身只是纯粹的数据载体,没有内置的过期或失效机制。要实现“限时可扫描”的效果,核心思路是把「原始文本+过期时间」打包后编码进二维码,然后在扫描验证环节检查当前时间是否超过过期时间。

下面分生成和验证两个环节给你具体的实现方案:


一、生成带过期信息的二维码

我们可以先定义一个结构体来封装原始内容和过期时间,然后把这个结构体序列化为JSON数据,再传给二维码生成器。这样二维码里就包含了判断是否过期的关键信息。

1. 定义内容结构体

首先创建一个遵循Codable的结构体,方便序列化和反序列化:

import Foundation

struct TimedQRContent: Codable {
    let originalText: String       // 用户输入的原始文本
    let expirationTimestamp: TimeInterval // 过期时间的时间戳(自1970年以来的秒数)
}

2. 修改生成二维码的代码

更新你原来的generateCodePressed方法,把用户输入的文本和过期时间打包成JSON,再生成二维码:

@IBOutlet weak var myImageView: UIImageView!
@IBOutlet weak var myTextField: UITextField!
var filter: CIFilter!

@IBAction func generateCodePressed(_ sender: UIButton){
    guard let inputText = myTextField.text, !inputText.isEmpty else {
        // 处理空输入的情况,比如提示用户输入内容
        return
    }
    
    // 计算一周后的时间戳(7天 = 7*24*3600秒)
    let oneWeekInSeconds: TimeInterval = 7 * 24 * 3600
    let expirationTimestamp = Date().addingTimeInterval(oneWeekInSeconds).timeIntervalSince1970
    
    // 创建带过期信息的内容对象
    let qrContent = TimedQRContent(originalText: inputText, expirationTimestamp: expirationTimestamp)
    
    // 把结构体序列化为JSON数据
    guard let jsonData = try? JSONEncoder().encode(qrContent) else {
        print("Failed to encode QR content")
        return
    }
    
    // 生成二维码
    filter = CIFilter(name: "CIQRCodeGenerator")
    filter.setValue(jsonData, forKey: "inputMessage")
    filter.setValue("H", forKey: "inputCorrectionLevel") // 设置高纠错级别,提升扫描容错率
    
    if let outputImage = filter.outputImage {
        // 缩放二维码,避免模糊
        let scaleTransform = CGAffineTransform(scaleX: 10, y: 10)
        let scaledImage = outputImage.transformed(by: scaleTransform)
        myImageView.image = UIImage(ciImage: scaledImage)
    }
}

这里有个小优化:把原来的.ascii编码换成JSON的UTF-8编码,这样可以支持中文等非英文字符,兼容性更好。


二、扫描时验证二维码是否过期

当用户扫描二维码后,需要解析出里面的JSON数据,然后对比当前时间和过期时间,判断二维码是否有效:

// 假设扫描得到的二维码数据是scannedData: Data
func validateTimedQRCode(scannedData: Data) -> String? {
    // 反序列化JSON为TimedQRContent对象
    guard let qrContent = try? JSONDecoder().decode(TimedQRContent.self, from: scannedData) else {
        // 二维码数据格式错误,直接判定无效
        return nil
    }
    
    // 获取当前时间的时间戳
    let currentTimestamp = Date().timeIntervalSince1970
    
    // 检查是否过期
    if currentTimestamp <= qrContent.expirationTimestamp {
        // 未过期,返回原始文本
        return qrContent.originalText
    } else {
        // 已过期,返回nil或者提示用户
        return nil
    }
}

三、进阶:提升安全性(防止篡改)

上面的方案是客户端本地验证,如果用户修改设备系统时间,可能会绕过过期检查。如果需要更高的安全性,建议结合后端验证:

  1. 生成二维码时,把原始文本和过期时间发送给后端,后端生成一个基于这些信息的签名(比如HMAC-SHA256)。
  2. 把「原始文本+过期时间+签名」一起编码进二维码。
  3. 扫描后,把这些数据发送给后端,由后端验证签名的合法性和是否过期,返回验证结果。

示例结构体可以改成:

struct SecureTimedQRContent: Codable {
    let originalText: String
    let expirationTimestamp: TimeInterval
    let signature: String // 后端生成的签名
}

总结一下:二维码本身不会自动失效,必须通过在数据中嵌入过期信息,再配合扫描时的时间校验来实现限时功能。如果对安全性要求高,一定要结合后端验证哦。

内容的提问来源于stack exchange,提问作者muradbay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 16:17:32