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

iOS 17.4.1 Widget二维码无法渲染问题求助

iOS 17.4.1 Widget二维码渲染失效问题

搭载iOS 17.4.1的iPhone 12设备上,Widget中的二维码无法正常显示,仅展示App logo,Widget其余内容显示正常。该功能在iOS 17及更早版本中运行完全正常,升级至iOS 17.4.1后仅Widget内的二维码渲染失效,App内的二维码生成功能无异常。使用Xcode 15.3的iOS 17.4模拟器测试时,Widget二维码功能正常。

询问:是否有其他开发者遇到iOS 17.4.1 Widget的该问题?是否存在已知的解决方法或修复方案?


复现代码

QRCodeSmallWidgetView

import SwiftUI
import WidgetKit

struct QRCodeSmallWidgetView: View {
    
    // Create the UserDefaults suites for Widget
    let appWidgetSuite = UserDefaults(suiteName: "group.zxc.asd.app.Abc-Widget")
    
    var body: some View {
        
        ZStack {
            
            // widget content
            if let userURL = appWidgetSuite?.string(forKey: "UserWidgetQRCode") {
                
                let imgQR = UIImage().generateQRCodeFromString(barcode: userURL)
                
                let qrImage = UIImage().convert(imgQR)
                
                let qrImageWithAppLogo = UIImage().addAppLogoToQRCodeInWidget(qrCodeImage: qrImage, logoImage: UIImage(named: "ic_qr_logo"))
                
                // Here Pass qrImage | qrImageWithAppLogo
                Image(uiImage: qrImageWithAppLogo)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            } else {
                Text("Add APP QR")
            }
        }
        .widgetBackground(Color(UIColor.systemBackground))
    }
}

struct QRCodeSmallWidgetView_Previews: PreviewProvider {
    static var previews: some View {
        QRCodeSmallWidgetView()
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}

extension View {
    func widgetBackground(_ backgroundView: some View) -> some View {
        if #available(iOSApplicationExtension 17.0, *) {
            return containerBackground(for: .widget) {
                backgroundView
            }
        } else {
            return background(backgroundView)
        }
    }
}

QRCodeWidgetEntryView

import SwiftUI
import WidgetKit

struct QRCodeWidgetEntryView: View {
    var entry: Provider.Entry

    @Environment(\.widgetFamily) var family

    @ViewBuilder
    var body: some View {
        switch family {
        case .systemSmall:
            QRCodeSmallWidgetView()

        default:
            fatalError()
        }
    }
}

App_WidgetBundle

import WidgetKit
import SwiftUI

@main
struct App_WidgetBundle: Widget {
    let kind: String = "App_WidgetBundle"

    var body: some WidgetConfiguration {
        
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            QRCodeWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("App QRCode Widget")
        .description("Instantly share your QRCode from your home screen.")
        .supportedFamilies([.systemSmall])
    }
}

Provider

import WidgetKit
import SwiftUI

struct Provider: TimelineProvider {
    typealias Entry = SimpleEntry

    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), qrImage: "staticQRCode")
    }

    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), qrImage: "staticQRCode")
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {

        let entry = SimpleEntry(date: Date(), qrImage: "")
        let timeline = Timeline(entries: [entry], policy: .atEnd)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let qrImage: String
}

UIImage 扩展

extension UIImage {
    
    func generateQRCodeFromString(barcode: String) -> CIImage {
        
        guard let dataString = barcode.data(using: .ascii) else {
            fatalError("Failed to convert string to data.")
        }
        
        guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else {
            fatalError("Failed to create CIFilter.")
        }
        
        qrFilter.setValue(dataString, forKey: "inputMessage")
        qrFilter.setValue("Q", forKey: "inputCorrectionLevel")
        
        guard let outputImage = qrFilter.outputImage else {
            fatalError("Failed to generate output image.")
        }
        
        let transform = CGAffineTransform(scaleX: 5.0, y: 5.0)
        return outputImage.transformed(by: transform)
    }
    
    func convert(_ cmage: CIImage) -> UIImage {
        
        let context: CIContext = CIContext.init(options: nil)
        let cgImage: CGImage = context.createCGImage(cmage, from: cmage.extent)!
        let image: UIImage = UIImage.init(cgImage: cgImage)
        return image
    }
    
    func addAppLogoToQRCodeInWidget(qrCodeImage: UIImage, logoImage: UIImage?) -> UIImage {
        
        let size = CGSize(width: qrCodeImage.size.width, height: qrCodeImage.size.height)
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        
        qrCodeImage.draw(in: CGRect(origin: CGPoint.zero, size: size))
        
        // Calculate the position to place the logo in the center
        let logoSize = CGSize(width: size.width * 0.48, height: size.height * 0.22)
        let origin = CGPoint(x: (size.width - logoSize.width) / 2, y: (size.height - logoSize.height) / 2)
        
        logoImage?.draw(in: CGRect(origin: origin, size: logoSize))
        
        let finalImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        
        return finalImage
    }
}

可能的解决方向
  1. 将二维码生成逻辑移至TimelineProvider
    Widget的body渲染线程有严格的性能限制,iOS 17.4.1可能收紧了同步图形操作的限制。建议在Provider的getTimeline方法中提前生成二维码,将生成后的图片数据(如Base64编码)存入App Group的UserDefaults,或直接传递到SimpleEntry中,在View中直接加载预生成的图片。

  2. 替换图片合成方式
    避免使用UIGraphicsBeginImageContextWithOptions在Widget中合成图片,改用SwiftUI的视图叠加方式实现logo添加:

    ZStack {
        Image(uiImage: qrImage)
            .resizable()
            .aspectRatio(contentMode: .fit)
        Image("ic_qr_logo")
            .resizable()
            .frame(width: qrImage.size.width * 0.48, height: qrImage.size.height * 0.22)
    }
    
  3. 使用第三方QR生成库
    替换Core Image的CIQRCodeGenerator,使用纯Swift的QR生成库(如QRCode.swift),避免系统版本带来的滤镜兼容性问题。

  4. 检查资源与权限

    • 确认ic_qr_logo图片已添加至Widget target的资源文件中
    • 验证App Group配置正确,Widget可正常读写UserDefaults中的UserWidgetQRCode值
  5. 异步生成与Timeline刷新
    在Widget中通过Task异步生成二维码,生成完成后调用WidgetCenter.shared.reloadAllTimelines()刷新Widget,但需注意Widget中异步操作的时间限制。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:39:55