ViewModel juaj përshtat modelin e aplikacionit tuaj me pamjen e tij. Me fjalë të tjera, ai ruan çdo gjendje që duhet të shfaqë pamja (në formën e vetive të lidhshme) dhe ekspozon API për të përditësuar atë gjendje dhe për të bërë "punën" e aplikacionit tuaj (në formën e metodave të thjeshta të vjetra). Pra, duke gjykuar nga ajo që keni shkruar:
"Unë kam një kontrollues shikimi që shfaq disa të dhëna të kërkuara nga një pikë fundore HTTP."
Duket sikur të filloni me, ViewModel juaj duhet të ketë një mënyrë për t'i përfaqësuar këto të dhëna si gjendje. Kjo pothuajse gjithmonë mund të bëhet me vetitë Objective-C:
@interface MyViewModel : NSObject
@property (nonatomic, strong) NSArray *tableData;
// (Or whatever makes sense for your view.)
@property (nonatomic) BOOL needCredentials;
@end
Më pas kontrolluesi juaj i pamjes duhet të lidhet me këto veti në mënyrë që sa herë që ndryshon një veçori (p.sh., sa herë që merren të dhëna të reja ose merret një gabim 401), UIView-të përkatëse të përditësohen. Vini re se API-ja e ViewModel-it tuaj nuk ka as ndonjë kod ReactiveCocoa. Kjo sepse nëse kontrolluesi juaj i pamjes ka një referencë për objektin ViewModel, kontrolluesi i pamjes mund të përdorë ReactiveCocoa për t'u lidhur me ViewModel në çfarëdo mënyre që ka kuptim. Për shembull, në rrethana më të thjeshta mund të përdorni vetëm RAC(self, infoView.name) = RACObserve(self, myViewModel.infoViewName);
. Në raste më komplekse, siç është zbatimi i një UITableViewDelegate, do t'ju duhet të zbatoni metodat UITableViewDataSource, por është e njëjta ide. Për të shfaqur një dialog modal që kërkon emrin e përdoruesit dhe fjalëkalimin, mund të përdorni edhe diçka të tillë
- (void)viewDidLoad
{
self.myViewModel = [[ViewModel alloc] init];
@weakify(self);
[[RACObserve(self, myViewModel.needCredentials) ignore:@NO] subscribeNext:^(id _) {
@strongify(self);
[self displayModalDialog];
}];
}
"Pra, unë dua ta bëj atë kërkesë HTTP. Nëse ka sukses, shkëlqyeshëm, shfaq të dhënat. Nëse dështon me një 401, më duhet t'i them pamjes që të hapë një dialog modal duke kërkuar emrin e përdoruesit/fjalëkalimin dhe më pas riprovo kërkesa HTTP."
ViewModel juaj mund të ketë një metodë të tillë si - (void)sendRequest:(NSDictionary *)parameters
. Thirrja e kësaj metode nga kontrolluesi juaj i pamjes mund të duket kështu:
- (IBAction)handleButtonTap:(id)sender
{
NSDictionary *parameters = [self makeParametersFromTextFields];
[self.myViewModel sendRequest:parameters];
}
Vini re përsëri: asnjë kod ReactiveCocoa nuk është i nevojshëm në API-në tuaj të ViewModel. Kjo nuk do të thotë se ju nuk duhet të përdorni RAC, vetëm se API-ja e një ViewModel nuk është domosdoshmërisht e varur nga sinjalet ose ndonjë koncept ReactiveCocoa – është thjesht një objekt model që është menduar posaçërisht për të shërbyer një pamje specifike në aplikacionin tuaj. Brenda implementimeve të metodës së ViewModel, mund të përdorni sinjale kudo, ose ndoshta po përdorni ndonjë API më të domosdoshme si NSOperationQueues ose diçka tjetër. Nuk ka shumë rëndësi, për sa kohë që ViewModel juaj i ekspozon të dhënat në pamje nëpërmjet vetive të vëzhgueshme nga KVO (në mënyrë që kontrolluesi juaj i pamjes të mund të lidhet me ato veti, gjë që zakonisht do të bëhej duke përdorur ReactiveCocoa).
Pra, çfarë bën metoda juaj -sendRequest:
me këtë fjalor parametrash? Unë nuk kam asnjë ide. Kjo pjesë varet nga ju. Nëse merr një përgjigje të vlefshme, duhet të përditësoni disa veti në ViewModel (për shembull, veçoria tableData
nga pjesa e kodit më lart). Nëse merr një 401
, ai duhet të përditësojë disa veti të tjera në ViewModel (për shembull, vendosni veçorinë needCredentials
në YES
). Kontrolluesi i pamjes, pasi është lidhur tashmë me këto veti, do të reagojë në çfarëdo mënyre që ju keni konfiguruar.
"Në ViewModel-in tim, pra, a kam dy sinjale? Njëri që kthen përmbajtjen dhe tjetri që i tregon shtresës së pamjes se më duhen kredencialet? Si t'i kthej kredencialet atje ku ndodh kërkesa HTTP?"
Unë shpresoj se deri në këtë pikë i jam përgjigjur pyetjes. ViewModel nuk ka nevojë për asnjë sinjale. Thjesht ka nevojë për veti të aftë për KVO. Dhe siç u demonstrua më lart në shembullin e metodës -handleButtonTap:
, nuk keni nevojë të bëni ndonjë gjë të veçantë për t'i çuar kredencialet deri në vendin ku ndodh kërkesa HTTP – thjesht thirrni një metodë në ViewModel dhe kaloni çdo të dhënë që ka kuptim. (Sigurisht, ViewModel duhet të dijë se cilit objekt t'i japë kredencialet në mënyrë që të fillojë kërkesën HTTP dhe të trajtojë përgjigjen, por ajo pjesë duhet të jetë mjaft akademike.)
28.12.2013
init
, etj. 28.12.2013-viewDidLoad
të kontrolluesit të pamjes. Megjithatë, kjo nuk është një kërkesë. Mund të ishte krijuar jashtë kontrolluesit të pamjes dhe të ishte transmetuar si parametër fillestar. Ose e instancuar në Ndërtuesin e Ndërfaqes dhe e lidhur me një pronë. Përdorni çdo gjë që është më e thjeshtë që ka kuptim për aplikacionin tuaj. 29.12.2013