Swift Widget、タップでアプリのナビゲーション先画面表示

Widget

タップ

struct Choi_CalEntryView : View {
    @Environment(\.widgetFamily) var family: WidgetFamily
    var entry: Provider.Entry

    var body: some View {
        GeometryReader { geometry in
            VStack(alignment: .leading) {
                HStack {
                    Spacer()
                    Text(entry.event.calenderTitle)
                        .font(.footnote)
                        .lineLimit(1)
                    Spacer()
                }
                RoundedRectangle(cornerRadius: 3, style: .circular)
                    .fill(entry.event.calendarColor)
                    .frame(width: geometry.size.width, height: 3, alignment: .center)
                switch self.family {
                case .systemSmall:
                    SmallView(entry: self.entry)
                case .systemMedium:
                    MiddleView(entry: self.entry)
                case .systemLarge:
                    Text("Large")
                default:
                    Text("default")
                }
                
            }
            .widgetURL(self.entry.event.url)
        }
        .padding(8)
    }
}

「func widgetURL(_ url: URL?) -> some View」を使用する。
アプリ側で判断がつくURLを設定する。
上記コードはユニークになるIDを使用してURLにしています。
necal://ユニークID

アプリ

Widgetのタップ受信

struct EventView: View {
    @EnvironmentObject var eventsModel: EventsModel
    @State var onEventList: Bool = false
    let event: EventDispModel
    
    var body: some View {
        NavigationLink(
            destination: EventListView(eventList: self.eventsModel.getEventList(calendars: [self.event.calendar]), title: self.event.calendar.title),
            isActive: self.$onEventList) {
            VStack(alignment: .leading, spacing: 8.0) {
                HStack {
                    Text(self.event.calendar.title)
                        .foregroundColor(Color(self.event.calendar.cgColor))
                    Spacer()
                }
                HStack {
                    Text(EventsModel.dateDisp(date: self.event.startDate, isAllDay: self.event.isAllDay))
                    Spacer()
                }
                HStack {
                    Text(self.event.eventTitle)
                    Spacer()
                }
            }
        }
        .onOpenURL(perform: { url in
            let ekcalendar = self.eventsModel.getEKCakendar(calendarIdentifier: url.absoluteString.replacingOccurrences(of: "necal://", with: ""))
            if event.calendar.calendarIdentifier == ekcalendar?.calendarIdentifier {
                print("onOpenURL:\(event.calendar.title)")
                self.onEventList.toggle()
            }
        })
    }
}

「func onOpenURL(perform action: @escaping (URL) -> ()) -> some View」を使用する。
受けたい場所に追加する。
例えば、複数表示されるサブViewに追加すると、各サブViewでコールされる。
上記コードは複数コールされる場所。
自分の情報と比較して対象時にアクション(上記コードの場合はNavigationLink遷移)実施。

ナビゲーション先を表示

NavigationLinkの「init(destination: Destination, isActive: Binding, label: () -> Label)」を使用する。
actionSheet等と同じ仕組み。trueにする事で遷移(表示)。

SwiftSwift

Posted by shi-n