前提
実務経験などがなくて自己研鑽で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"
}
}
}
}
以上、気になる部分があればご指摘ください。