例によるSwiftUI(SwiftUI by Example)14 Composing views

カスタムビューを作成および作成する方法
How to create and compose custom views

SwiftUIの中心的な信条の1つは構成です。つまり、多くの小さなビューを作成し、それらを組み合わせてより大きなものを作成するように設計されています。これにより、ビューを大規模に再利用できるようになり、作業が減ります。さらに良いことに、小さなサブビューを組み合わせると、実行時のオーバーヘッドが実質的にないため、自由に使用できます。

重要なのは、小さなことから始めて、上に向かって進むことです。たとえば、多くのアプリは次のようなユーザーと連携する必要があります。

//-----------------------------------
struct User {
    var name: String
    var jobTitle: String
    var emailAddress: String
    var profilePicture: String
}
//-----------------------------------
struct ProfilePicture: View {
    var imageName: String

    var body: some View {
        Image(imageName)
            .resizable()
            .frame(width: 70, height: 70)
            //.clipShape(Circle())
    }
}
//-----------------------------------
struct EmailAddress: View {
    var address: String

    var body: some View {
        HStack {
            Image(systemName: "envelope")
            Text(address)
        }
    }
}
//-----------------------------------
struct UserDetails: View {
    var user: User

    var body: some View {
        VStack(alignment: .leading) {
            Text(user.name)
                .font(.largeTitle)
                .foregroundColor(.primary)
            Text(user.jobTitle)
                .foregroundColor(.secondary)
            EmailAddress(address: user.emailAddress)
        }
    }
}
//-----------------------------------
struct UserView: View {
    var user: User

    var body: some View {
        HStack {
            ProfilePicture(imageName: user.profilePicture)
            UserDetails(user: user)
        }
    }
}
//-----------------------------------
struct ContentView: View {
    let user = User(name: "Paul Hudson", jobTitle: "Editor, Hacking with Swift", emailAddress: "paul@hackingwithswift.com", profilePicture: "dokuro")

    var body: some View {
        UserView(user: user)
    }
}
//-----------------------------------

How to combine text views together

SwiftUI’s text view overloads the + operator so that you can combine them together to make new text views.

//-----------------------------------
struct UserView: View {
    var user: User

    var body: some View {
        VStack{
            Text("SwiftUI ")
                .font(.largeTitle)
            + Text("is ")
                .font(.headline)
            + Text("awesome")
                .font(.footnote)
            //--------------
            Text("SwiftUI ")
                .foregroundColor(.red)
            + Text("is ")
                .foregroundColor(.orange)
                .fontWeight(.black)
            + Text("awesome")
                .foregroundColor(.blue)
        }
    }
}
//-----------------------------------

ビューをプロパティとして保存する方法
How to store views as properties

複数のビューが別のビュー内にネストされている場合は、レイアウトコードを簡単にするために、それらの一部またはすべてのプロパティを作成すると便利な場合があります。次に、これらのプロパティをビューコード内でインラインで参照して、明確に保つことができます。

たとえば、これにより2つのテキストビューがプロパティとして作成され、それらがVStack:内に配置されます。

//-----------------------------------
struct ContentView: View {
    let title = Text("Paul Hudson")
                    .font(.largeTitle)
    let subtitle = Text("Author")
                    .foregroundColor(.secondary)

    var body: some View {
//        VStack {
//            title
//            subtitle
//        }
        VStack {
            title
                .foregroundColor(.red)
            subtitle
        }
    }
}
//-----------------------------------

カスタム修飾子を作成する方法
How to create custom modifiers

同じモディファイアのセットをビューに常にアタッチしていることに気付いた場合(たとえば、背景色、パディング、特定のフォントなど)、これらすべての変更をカプセル化するカスタムビューモディファイアを作成することで重複を回避できます。 。したがって、「赤にする、大きなフォントを使用する」などと言うのではなく、「警告のように見せる」と言って、事前に作成された修飾子のセットを適用することができます。

独自に作成する場合は、ViewModifierプロトコルに準拠する構造体を定義します。このプロトコルでは、body(content:)ある種のコンテンツを必要に応じて変換し、結果を返すメソッドを受け入れる必要があります。

たとえば、これにより、PrimaryLabelパディング、赤い背景、白いテキスト、および大きなフォントを追加する新しい修飾子が作成されます。

//-----------------------------------
struct PrimaryLabel: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.red)
            .foregroundColor(Color.white)
            .font(.largeTitle)
    }
}
//-----------------------------------
struct ContentView: View {
    var body: some View {
        Text("Hello, SwiftUI")
            .modifier(PrimaryLabel())
    }
}
//-----------------------------------

SwiftUIのカスタムUIViewをラップする方法
How to wrap a custom UIView for SwiftUI

SwiftUIはUIKitのUIViewサブクラスの多くを提供するのに優れていますが、現時点ではまだすべてを備えているわけではありません。幸いなことに、必要なカスタムラッパーを作成するのは難しくありUIViewません。

例として、の単純なSwiftUIラッパーを作成しましょうUITextView。これには4つのステップがあります。

に準拠する構造体を作成しUIViewRepresentableます。
使用しているテキスト文字列を格納する1つのプロパティを定義します。
それを与えるmakeUIView()私達のテキストビューを返します方法を。
updateUIView()テキストビューのデータが変更されるたびに呼び出されるメソッドを追加します。

//-----------------------------------
struct TextView: UIViewRepresentable {
    @Binding var text: String

    func makeUIView(context: Context) -> UITextView {
        return UITextView()
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = text
    }
}
//-----------------------------------
struct ContentView : View {
    @State var text = ""

    var body: some View {
        TextView(text: $text)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    }
}
//-----------------------------------

テキストに画像を挿入する方法
How to insert images into text


//-----------------------------------
struct ContentView : View {
    @State var text = ""

    var body: some View {
        VStack{
            Text("Hello ") + Text(Image(systemName: "star")) + Text(" World!")
            
            (Text("Hello ") + Text(Image(systemName: "star")) + Text(" World!"))
                .foregroundColor(.blue)
                .font(.largeTitle)
            
            Text("Hello ") + Text(Image(systemName: "star")) + Text(" World!")
                .foregroundColor(.blue)
                .font(.largeTitle)
            
            Text("Hello ") + Text(Image("dokuro")) + Text(" World!")
                    
        }
    }
}
//-----------------------------------