Swifui小部件,每秒图像重新加载导致内存填满

我学习如何第一次创建小部件。我已经完成了设计,一切都很好,我准备好把它放在我的应用程序上。但是,我发现仍然需要解决的问题。我正在进行每秒更新的倒计时。在更新时,它每秒写入全新图像并构建内存,而磁盘显示每秒20-30MB,CPU卡在90-95%。如何在不更新图像的情况下更新标签?

我的主要代码:

struct Provider: IntentTimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), configuration: ConfigurationIntent())
    }

    func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), configuration: configuration)
        completion(entry)
    }

    func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        let currentDate = Date()
        let entryDate = Calendar.current.date(byAdding: .second, value: 1, to: currentDate)!
        let entry = SimpleEntry(date: entryDate, configuration: configuration)
        entries.append(entry)

        let timeline = Timeline(entries: entries, policy: .atEnd)
        
        let _ =  Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timerSec) in
            WidgetCenter.shared.reloadAllTimelines()
        }
        
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let configuration: ConfigurationIntent
}

struct Widget_Practice_WidgetEntryView : View {
    @Environment(\.widgetFamily) var family
    var entry: Provider.Entry
    
    var body: some View {
        switch family {
        case .systemSmall: CreateSmallDesign()
        case .systemMedium: CreateMediumDesign()
        case .systemLarge: CreateLargeDesign()
        case .systemExtraLarge: CreateExLargeDesign()
        @unknown default: CreateSmallDesign()
        }
    }
}

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

    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            Widget_Practice_WidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Edit Widget")
        .description("This is an example widget.")
    }
}

struct Widget_Practice_Widget_Previews: PreviewProvider {
    static var previews: some View {
        Widget_Practice_WidgetEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}

实际上我的中等大小视图代码:

struct CreateMediumDesign : View {
    var body: some View {
        ZStack {
            Image(uiImage: resizeImage(image: UIImage(named: demoCountdownDatabase[1].imageName), targetSize: CGSize(width: 250, height: 250))!)
                .resizable()
                .scaledToFill()
                .blur(radius: 30)
            
            VStack {
                HStack(alignment: .center, spacing: 15) {
                    Text("")
                    Image(uiImage: resizeImage(image: UIImage(named: demoCountdownDatabase[1].imageName), targetSize: CGSize(width: 250, height: 250))!)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 80, height: 80, alignment: .center)
                        .clipShape(RoundedRectangle(cornerRadius: 15))
                        .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.white, lineWidth: 2))
                        .shadow(radius: 10)
                    VStack(alignment: .leading) {
                        Text(demoCountdownDatabase[1].title)
                            .font(.largeTitle)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .scaledToFill()
                        Text(demoCountdownDatabase[1].subtitle)
                            .font(.body)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .scaledToFill()
                    }
                    Spacer()
                }
                
                GeometryReader { geometry in
                    HStack(alignment: .center, spacing: 0) {
                        Text(fullDateUntilString(date: demoCountdownDatabase[1].toDate, title: "Year"))
                            .font(.footnote)
                            .frame(width: geometry.size.width / 6.1, height: 35)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .multilineTextAlignment(.center)
                        Text(fullDateUntilString(date: demoCountdownDatabase[1].toDate, title: "Month"))
                            .font(.footnote)
                            .frame(width: geometry.size.width / 6.1, height: 35)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .multilineTextAlignment(.center)
                        Text(fullDateUntilString(date: demoCountdownDatabase[1].toDate, title: "Day"))
                            .font(.footnote)
                            .frame(width: geometry.size.width / 6.1, height: 35)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .multilineTextAlignment(.center)
                        Text(fullDateUntilString(date: demoCountdownDatabase[1].toDate, title: "Hour"))
                            .font(.footnote)
                            .frame(width: geometry.size.width / 6.1, height: 35)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .multilineTextAlignment(.center)
                        Text(fullDateUntilString(date: demoCountdownDatabase[1].toDate, title: "Minute"))
                            .font(.footnote)
                            .frame(width: geometry.size.width / 6.1, height: 35)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .multilineTextAlignment(.center)
                        Text(fullDateUntilString(date: demoCountdownDatabase[1].toDate, title: "Second"))
                            .font(.footnote)
                            .frame(width: geometry.size.width / 6.1, height: 35)
                            .foregroundColor(.white)
                            .shadow(color: .black, radius: 2, x: 0, y: 0)
                            .multilineTextAlignment(.center)
                    }
                }
                .frame(height: 15)
            }
        }
    }
}

我的代码要调整图像大小以减少其大小:


func resizeImage(image: UIImage?, targetSize: CGSize) -> UIImage? {
    if image != nil {
        let size = image!.size

        let widthRatio  = targetSize.width  / size.width
        let heightRatio = targetSize.height / size.height

        var newSize: CGSize
        if(widthRatio > heightRatio) {
            newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
        } else {
            newSize = CGSize(width: size.width * widthRatio,  height: size.height * widthRatio)
        }
        
        let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

        UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
        image!.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage ?? nil
    } else {
        return nil
    }
}

Thank you very much.

Does this answer your question? updating时间文本在WidgetKit中每分钟标记Lorem Ipsum
nope,刷新图像并积聚内存。我使用你给了我的方法链接,它工作但仍然刷新图像原因内存/磁盘/和CPU Go螺母。我只想要重新加载文本,忽略更新图像TravgAlax
Widgets就像截图。每个时间轴条目都是屏幕截图。Text with style最接近你的要求。lorem ipsum
Widgets还有预算,可以根据用户查看窗口小部件的次数增加或减少。developer.apple.com/documentation/widgetkit/...Lorem Ipsum

回答 0