13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftUIとStoryBoardの共存時期の過ごし方 for watchOS

Posted at

そろそろSwiftUI使ってもいいよね?

iOS14betaも発表されて、そろそろエンタープライズアプリもiOS13対応が許される季節になってきましたが、皆様いかがお過ごしでしょうか?
と言っても、実際には過去のプロジェクトはStoryboardで沢山の画面が作られているわけで、むしろ僕の触ってるプロジェクトはそもそもObjective-Cだったりするんですが、利用現場の端末のバージョンも上がってきて、そろそろiOS13 / watchOS6の機能を使えるような空気が漂ってきました。

iOSでStoryboardとSwiftUIを混ぜる方法は こちらの記事を参考にさせていただいて非常に助かりました。

ところが開発者の少ないwatchOS関連は探してもなかなか見つからないのです。そうですね。仕方ないからメモを残しておきます。
業務の終わりのタイミングで書いてるので本当にメモです。

storyboardなInterfaceControllerからSwiftUIに遷移

既存のInterfaceControllerからSwiftUIを呼ぶには、WKHostingController を使います。
https://developer.apple.com/documentation/swiftui/wkhostingcontroller

WKHostingController は InterfaceControllerを継承しているので、今までと同じ感覚でクラスを連携させれば呼べます。

まずは、今までのWKInterfaceControllerの代わりに WKHostingControllerでコントローラーclassを作ります。

HomeViewInterfaceController.swift

import SwiftUI

class HomeViewInterfaceController : WKHostingController<HomeView> {
    override var body: HomeView {
        return HomeView()
    }
}
HomeView.swift
import SwiftUI

struct Menu: Identifiable{
    var id: Int
    var name: String
    
    init(id: Int, name: String){
        self.id = id
        self.name = name
    }    
}

class MenuList: ObservableObject{
    @Published var list: [Menu]

    init(){
        self.list = [
            Menu(id: 1, name:"Apple"),
            Menu(id: 2, name:"Banana"),
            Menu(id: 3, name:"Cookie"),
            Menu(id: 4, name:"Donuts")]
    }    
}

struct HomeView: View {
    @ObservedObject var mymenu: MenuList = MenuList()
    
    var body: some View {
        List {
            ForEach(mymenu.list){ item in
                NavigationLink(destination: SecondView(id: item.id)) {
                    Text("\(item.name)")
                }
            }
        }
    }
}

storyboardにinterfaceControllerを追加して、参照先のclassをHomeViewInterfaceController.swift に Identifierを "HomeViewInterfaceController"にします。
スクリーンショット 2020-07-09 17.43.56.png

InterfaceControllerから SwiftUIを呼び出すには

InterfaceController.m
    [self pushControllerWithName:@"HomeViewInterfaceController" context:nil];

//rootViewとして呼び出すには
    [WKInterfaceController reloadRootPageControllersWithNames:@[@"HomeViewInterfaceController"] contexts:nil orientation:WKPageOrientationVertical pageIndex:0];

といつものようにIdentifierを指定してあげればOK。

HomeからSwiftUIで定義されているSecondViewを呼び出すには、上の

                NavigationLink(destination: SecondView(id: item.id)) {
                    Text("\(item.name)")
                }

で呼び出せます。

SwiftUIからwatchKitのstoryboardのInterfaceControllerに遷移

public init(destinationName: String, @ViewBuilder label: () -> Label)

を使います。

NavigationLink(destinationName: "second") {
    Text("\(item.name)")
}

SwiftUIからstoryboard のInterfaceControllerでrootViewsをリセット

            Button(action: {
                WKInterfaceController.reloadRootControllers(withNamesAndContexts: [(name: "second", context: [:] as AnyObject )])
            }){
                Text("second")
            }

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?