final public class Store<State: FluxState>: BindableObject {
public let willChange = PassthroughSubject<Void, Never>()
private(set) public var state: State
private func _dispatch(action: Action) {
willChange.send()
state = reducer(state, action)
}
}
هرکله چې تاسو یو عمل پیل کړئ، تاسو ګیربکس فعال کړئ. دا به د غوښتنلیک اوسني حالت سره سم عملونه ارزوي. دا به بیا د عمل ډول او معلوماتو سره سم یو نوی بدل شوی حالت بیرته راولي.
ښه، له هغه ځایه چې پلورنځی د بانډ ایبل آبجکټ دی ، نو دا به SwiftUI ته خبر ورکړي کله چې د دې ارزښت د پاسترو سبجیکٹ لخوا چمتو شوي willChange ملکیت په کارولو سره بدل شي. دا ځکه چې BindableObject باید د PublisherType چمتو کړي، مګر د پروتوکول پلي کول د دې اداره کولو مسولیت لري. په ټوله کې، دا د ایپل څخه خورا پیاوړی وسیله ده. په دې اساس، په راتلونکی رینډینګ دوره کې، SwiftUI به د دولت بدلون سره سم د نظرونو بدن وړاندې کولو کې مرسته وکړي.
په حقیقت کې ، دا د SwiftUI ټول زړه او جادو دی. اوس، په هر هغه نظر کې چې د یو دولت ګډون کوي، نظر به د دې له مخې وړاندې شي چې د دولت څخه کوم معلومات ترلاسه شوي او څه بدلون موندلی.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let controller = UIHostingController(rootView: HomeView().environmentObject(store))
window.rootViewController = controller
self.window = window
window.makeKeyAndVisible()
}
}
}
struct CustomListCoverRow : View {
@EnvironmentObject var store: Store<AppState>
let movieId: Int
var movie: Movie! {
return store.state.moviesState.movies[movieId]
}
var body: some View {
HStack(alignment: .center, spacing: 0) {
Image(movie.poster)
}.listRowInsets(EdgeInsets())
}
}
پلورنځي د چاپیریال آبجیکٹ په توګه انجیکشن کیږي کله چې غوښتنلیک پیل شي او بیا د @EnvironmentObject په کارولو سره په هر لید کې د لاسرسي وړ وي. د فعالیت جزا شتون نلري ځکه چې ترلاسه شوي ملکیتونه په چټکۍ سره ترلاسه کیږي یا د غوښتنلیک حالت څخه محاسبه کیږي.
پورته کوډ عکس بدلوي که چیرې د فلم پوسټر بدل شي.
او دا په حقیقت کې یوازې د یوې کرښې سره ترسره کیږي، د کوم نظر په مرسته چې د دولت سره تړاو لري. که تاسو په iOS یا حتی کې د ReSwift سره کار کړی وي سره نښلوي د عکس العمل سره ، تاسو به د SwiftUI جادو پوه شئ.
اوس تاسو کولی شئ د عمل فعالولو هڅه وکړئ او نوی حالت خپور کړئ. دلته یو ډیر پیچلی مثال دی.
struct CustomListDetail : View {
@EnvironmentObject var store: Store<AppState>
let listId: Int
var list: CustomList {
store.state.moviesState.customLists[listId]!
}
var movies: [Int] {
list.movies.sortedMoviesIds(by: .byReleaseDate, state: store.state)
}
var body: some View {
List {
ForEach(movies) { movie in
NavigationLink(destination: MovieDetail(movieId: movie).environmentObject(self.store)) {
MovieRow(movieId: movie, displayListImage: false)
}
}.onDelete { (index) in
self.store.dispatch(action: MoviesActions.RemoveMovieFromCustomList(list: self.listId, movie: self.movies[index.first!]))
}
}
}
}
په پورته کوډ کې، زه د هر IP لپاره د SwiftUI څخه .onDelete عمل کاروم. دا په لیست کې قطار ته اجازه ورکوي چې د حذف کولو لپاره نورمال iOS سویپ ښکاره کړي. نو کله چې کاروونکي د حذف کولو تڼۍ ته لاس واچوي، دا ورته عمل هڅوي او فلم له لیست څخه لرې کوي.
func moviesStateReducer(state: MoviesState, action: Action) -> MoviesState {
var state = state
switch action {
// other actions.
case let action as MoviesActions.AddMovieToCustomList:
state.customLists[action.list]?.movies.append(action.movie)
case let action as MoviesActions.RemoveMovieFromCustomList:
state.customLists[action.list]?.movies.removeAll{ $0 == action.movie }
default:
break
}
return state
}
کمونکی اجرا کیږي کله چې تاسو یو عمل واستوئ او یو نوی حالت بیرته راوباسئ ، لکه څنګه چې پورته ویل شوي.
زه به لاهم توضیحاتو ته لاړ نه شم - څنګه SwiftUI واقعیا پوهیږي چې څه باید ښودل شي. د دې لپاره چې ډیر ژور پوه شي، دا ارزښت لري د معلوماتو جریان په اړه د WWDC سیشن وګورئ په SwiftUI کې. دا په تفصیل سره تشریح کوي چې ولې او کله کارول کیږي د بهرنیو چارو, @Binding، ObjectBinding او EnvironmentObject.