У меня возникла проблема с виджетом в моем приложении iOS, из-за которой QRCode не отображается правильно на iPhone 12 с iOS 17.4.1.
Эта функция отлично работала во всех версиях до iOS 17. После обновления до iOS 17.4.1 QRCode больше не отображается в виджете. Остальная часть содержимого виджета отображается так, как ожидалось, но представление QRCode отсутствует. Я подтвердил, что код генерации QRCode отлично работает внутри самого приложения и не работает только в виджете последней версии iOS. Я также пробовал разные подходы, чтобы убедиться, что это не проблема рендеринга, но, похоже, ничего не работает. Кто-нибудь еще сталкивался с этой проблемой с виджетами в iOS 17.4.1, и есть ли известный способ обхода или исправления этой проблемы?
Я также проверил, что с Xcode 15.3, Simulator (17.4) он работает нормально, но в iPhone 12 (iOS 17.4.1) он просто показывает логотип приложения в виджете QRCode вместо QRCode.
Здесь я прикрепил код, необходимый для воспроизведения проблемы.
вот код 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])
}
}
вот код провайдера:
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
}
}
Спасибо за ваш ответ. Здесь я также прикрепил отсутствующий код расширения UIImage, не могли бы вы проверить и помочь. @Paulw11





static func generateQRCodeFromString(barcode: String) -> UIImage? {
guard let data = barcode.data(using: String.Encoding.ascii) else { return nil }
var uiImage: UIImage?
if let filter = CIFilter(
name: "CIQRCodeGenerator",
parameters: ["inputMessage": data, "inputCorrectionLevel": "Q"]
) {
guard
let outputImage = filter.outputImage,
let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent)
else {
return nil
}
let scaleFactor: CGFloat = 12
let size = CGSize(
width: outputImage.extent.width * scaleFactor,
height: outputImage.extent.height * scaleFactor
)
UIGraphicsBeginImageContext(size)
if let context = UIGraphicsGetCurrentContext() {
context.interpolationQuality = .none
context.draw(cgImage, in: CGRect(origin: .zero, size: size))
uiImage = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
}
return uiImage
}
Настоящая проблема заключалась в логике создания изображений. Здесь я просто меняю две вышеуказанные функции, которые преобразуют CIImage в UIImage, как указано выше, и теперь все работает нормально.
Являются ли
generateQRCodeFromString,convertиaddAppLogoToQRCodeInWidgetрасширениямиUIImage? Почему они реализованы как расширения, если они, похоже, не работают с UIImage? Где этот код? Похоже, что этот код, скорее всего, имеет проблему