LoginSignup
1
0

フロントエンドの自分がSwiftUI学んでみました感想

Posted at

前提

実務経験などがなくて自己研鑽でSwiftUIを学んでみました。
気づいてことを書いてみましたので、もし間違っている部分があったらご指摘いただけると幸いです!

感想1

状態管理の部分については、ReactのuseStateとSwiftUIの@Stateは似ていると思いました。
両方とも、コンポーネント内で状態を管理し、その状態が変更されるとコンポーネントが再レンダリングされるという点で共通しています。

ReactはReact HooksのuseStateでstateを保持したり更新したりする:

  const MyComponent = () => {
    const [name, setName] = useState('testName');
    const changeName = () => {
      setName('changedName');
    };
    return (
      <div>
        <p>My name is {name}</p>
        <button onClick={changeName}>change name</button>
      </div>
    );
  };

SwiftUIでは、@Stateプロパティラッパーを使用して状態を管理します:

struct MyView: View {
    @State private var name = "testName"

    var body: some View {
        VStack {
            Text("My name is \(name)")
            Button("change name") {
                name = "changedName"
            }
        }
    }
}
struct MyView_Previews: PreviewProvider {
    static var previews: some View {
        MyView()
    }
}

感想2

親コンポーネントから子コンポーネントにデータを渡すためReactのcontextとSwiftUIの@EnvironmentObjectも似ていると思いました。
ただReactのcontextは通常、プロバイダーとコンシューマーのパターンを使用してデータを渡し、@EnvironmentObjectはSwiftUIの環境変数として直接注入されます。

Reactはcontextにより、コンポーネントツリー内でグローバルにデータを共有することで、親コンポーネントで状態や関数を定義し、子コンポーネントでそれらを利用することができます:

  const MyContext = createContext({});
  const ParentComponet = () => {
    const [name, setName] = useState('testName');
    return (
      <MyContext.Provider value={{ name, setName }}>
        <ChildComponent />
      </MyContext.Provider>
    );
  };
  const ChildComponent = () => {
    const { name, setName } = useContext(MyContext);
    return (
      <>
        <p>{name}</p>
        <button
          onClick={() => {
            setName('changedName');
          }}
        ></button>
      </>
    );
  };

SwiftUIの@EnvironmentObjectは、SwiftUIアプリ内でのデータの共有と似たような概念です。@EnvironmentObjectを使用すると、アプリ内のどこからでも同じオブジェクトを使用してデータにアクセスできます。これは、アプリ全体で共有されるデータを管理するために使用されます:

class MyModel: ObservableObject {
    @Published var name = "textName"
}

struct ParentView: View{
    @StateObject var myModel = MyModel()

    var body: some View {
        ChildView()
            .environmentObject(myModel)
    }
}

struct ChildView: View {
    @EnvironmentObject var model: MyModel
    var body: some View{
        VStack {
            Text("My Name is \(model.name)")
            Button("changed name") {
                model.name = "changeName"
            }
        }
    }
}

感想3

ReactとSwiftUIでは、データのフローを管理するために似たようなコンセプトとプロパティラッパーが提供されており、効果的なUIの構築とデータの同期を容易にしています。
Reactは親コンポーネントから子コンポーネントへのデータの流れていた方がいいというデータのフローを単方向に保つことが推奨されています:

  const ParentComponent = () => {
    const [count, setCount] = useState(0);
    const incrementCount = () => {
      setCount(count + 1);
    };

    return <ChildComponent count={count} incrementCount={incrementCount} />;
  };

SwiftUIでも同様に、データフローを管理しやすくするために、@State@Binding@ObservedObjectなどのプロパティラッパーが提供されていて、このように親コンポーネントで@Stateを使用してtextを管理し、子コンポーネントに@Bindingを使用してtextを渡すことができます:

struct ParentView: View {
    @State private var text = "testName"
    
    var body: some View {
        VStack {
            ChildView(text: $text)
        }
    }
}

struct ChildView: View {
    @Binding var text: String
    
    var body: some View {
        Text(text)
        Button("Change Name") {
            text = "changedName"
        }
    }
}

また、@ObservableObjectプロパティラッパーを使用して、UserDataクラスのインスタンスを監視し、UserDataクラスのnameプロパティが変更されるとビューが更新されるようにすることもできます:

class UserData: ObservableObject {
    @Published var name = "test name"
}

struct ContentView: View {
    @ObservedObject var userData = UserData()
    
    var body: some View {
        VStack {
            Text(userData.name)
            Button("Change Name") {
                self.userData.name = "changedName"
            }
        }
    }
}

以上、気になる部分があればご指摘ください。

1
0
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
1
0