fasky-software / flutter_widgetkit

Flutter library for iOS Widgets Extensions. Integrate a Widget into your App ๐Ÿ๐Ÿ“ฑ
MIT License
260 stars 23 forks source link

When I click widget, error occurs: NSInvalidArgumentException, nil error #18

Open spencer0124 opened 1 year ago

spencer0124 commented 1 year ago

It works well, but when i click to widget to launch the app, it always crashes Any idea how to solve error about NSInvalidArgumentException, nil error?

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]' *** First throw call stack: (0x1b7f04e38 0x1b108f8d8 0x1b80aa078 0x1b80b53ac 0x1b7f202b8 0x1b7f20158 0x100d9eae8 0x100d9efe8 0x103d679f0 0x103d489fc 0x100fb2164 0x1bae0cadc 0x1bb046798 0x1bb047338 0x1ba8cfb1c 0x1ba8cfe3c 0x1bae0c7b4 0x1bb046734 0x1bb0470e8 0x1bf51b460 0x1bf51cf88 0x1bf52b7f4 0x1bf52b444 0x1b7f956c8 0x1b7f7702c 0x1b7f7beb0 0x1f2171368 0x1ba471668 0x1ba4712cc 0x1007c2448 0x1d6874960) libc++abi: terminating with uncaught exception of type NSException

spencer0124 commented 1 year ago

I think it is weird because lock screen widget and home widget (generating barcode) works well, but whenever i click the widget to open the app directly, it always crashes. below is my flutter code and swift code.

==== 1. flutter code ==== WidgetKit.setItem( 'widgetData', jsonEncode(WidgetData( '${passwordController.text}10')), 'group.flutterioswidget1'); WidgetKit.reloadAllTimelines();

==== 2. swift code ==== // // skkupass_widget.swift // skkupass widget // // Created by --- on 2023/04/22. //

import WidgetKit import SwiftUI import Intents import CoreImage

struct FlutterData: Decodable, Hashable { let text: String }

struct SimpleEntry: TimelineEntry { let date: Date var flutterData: FlutterData? }

// ์–ธ์ œ ๊ฐฑ์‹ ํ•  ๊ฒƒ์ธ๊ฐ€? struct Provider: TimelineProvider {

// data๊ฐ€ ์—†์„๋•Œ ๋ณด์—ฌ์ค„ ์˜ˆ์‹œ (dummy data)
func placeholder(in context: Context) -> SimpleEntry {
    SimpleEntry(date: Date(), flutterData: FlutterData(text: "๊ฐœ์ธ์šฉ ๋ฐ”์ฝ”๋“œ๊ฐ€ ์—ฌ๊ธฐ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค"))
}

// ์‹ค์ œ ๊ด€๋ จ data
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
    let entry = SimpleEntry(date: Date(), flutterData: FlutterData(text: "๊ฐœ์ธ์šฉ ๋ฐ”์ฝ”๋“œ๊ฐ€ ์—ฌ๊ธฐ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค"))
    completion(entry)
}

// ์‹ค์ œ๋กœ timeline ๊ด€๋ จ๋œ ๋ถ€๋ถ„
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
    //var entries: [SimpleEntry] = []

    let sharedDefaults = UserDefaults.init(suiteName: "group.flutterioswidget1")
    var flutterData: FlutterData? = nil

        if(sharedDefaults != nil) {
                do {
                  let shared = sharedDefaults?.string(forKey: "widgetData")
                  if(shared != nil){
                    let decoder = JSONDecoder()
                    flutterData = try decoder.decode(FlutterData.self, from: shared!.data(using: .utf8)!)
                  }
                } catch {
                  print(error)
                }
            }

        let entryDate = Calendar.current.date(byAdding: .hour, value:24, to:Date())!
        let entry = SimpleEntry(date: entryDate, flutterData: flutterData)
        let timeline = Timeline(entries: [entry], policy: .never)
        completion(timeline)
}

}

func generateBarcode(from string: String) -> UIImage? { // Convert the string to data let data = string.data(using: .ascii)

    // Create a CIFilter for Code 128 barcode generation
    guard let filter = CIFilter(name: "CICode128BarcodeGenerator") else { return nil }

    // Set the input message for the filter
    filter.setValue(data, forKey: "inputMessage")

    // Get the output image from the filter
    guard let outputImage = filter.outputImage else { return nil }

    // Create a UIImage from the output image
    let context = CIContext()
    guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else { return nil }
    return UIImage(cgImage: cgImage)
}

struct skkupass_widget: Widget { let kind: String = "skkupass_widget"

var body: some WidgetConfiguration {
    StaticConfiguration(kind: kind, provider: Provider()) { entry in
         skkupasswidgetView(entry: entry)
    }
    .supportedFamilies([.systemMedium, .accessoryCircular, .accessoryInline, .accessoryRectangular])
    .configurationDisplayName("์Šค๊พธํŒจ์Šค ์œ„์ ฏ")
    .description("ํ•™์ƒ์ฆ ๋ฐ”์ฝ”๋“œ๋ฅผ ๋ณด์—ฌ์ฃผ๋ฉฐ, ํด๋ฆญ์‹œ ์•ฑ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค")
}

}

struct skkupasswidgetView: View { var entry: Provider.Entry

@Environment(\.widgetFamily) var family

@ViewBuilder
var body: some View {

    switch family {
    case .accessoryCircular:
        ZStack {
                Circle()
                    .fill(Color.black)
                Image("skkuinvert")
                    .resizable()
                    .frame(width: 57, height: 57)
            }

    case .accessoryRectangular:
        ZStack {
            HStack {
                Text("SKKU PASS")
                    .font(.headline)
                    .foregroundColor(.white)
            }
        }

    case .accessoryInline:
        Text("๐ŸŒฑ")

    case .systemMedium:

        ZStack {
            Color.white // set background color

            VStack {
                if let barcodeImage = generateBarcode(from: entry.flutterData?.text ?? "") {
                    Image(uiImage: barcodeImage)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .padding(0)
                }
            }
        }

    default:
        Text("error")
    }

}

}