建立一個類,繼承自TTTableViewController,當通過TTNavigator建立URL與對象的映射關係時會建立該新類的執行個體;當通過TTNavigator開啟URL時會將該對象的視圖加入到父視圖中([parentView addSubView:newViewController.view)。如果新類沒有重寫loadView方法,則會調用TTTableViewController的loadView方法,我們的旅程就從此開始:
TTTableViewController
TTTableViewController:- (void)loadView { [super loadView]; self.tableView;}
//建立tableView執行個體,TTTableView繼承自UITableView- (UITableView*)tableView { if (nil == _tableView) { _tableView = [[TTTableView alloc] initWithFrame:self.view.bounds style:_tableViewStyle]; _tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; UIColor* backgroundColor = _tableViewStyle == UITableViewStyleGrouped ? TTSTYLEVAR(tableGroupedBackgroundColor) : TTSTYLEVAR(tablePlainBackgroundColor); if (backgroundColor) { _tableView.backgroundColor = backgroundColor; self.view.backgroundColor = backgroundColor; } [self.view addSubview:_tableView]; } return _tableView;}
- (void)viewWillAppear:(BOOL)animated { //此處的super為TTModelViewController [super viewWillAppear:animated]; if (_lastInterfaceOrientation != self.interfaceOrientation) { _lastInterfaceOrientation = self.interfaceOrientation; [_tableView reloadData]; } else if ([_tableView isKindOfClass:[TTTableView class]]) { TTTableView* tableView = (TTTableView*)_tableView; tableView.highlightedLabel = nil; tableView.showShadows = _showTableShadows; } [_tableView deselectRowAtIndexPath:[_tableView indexPathForSelectedRow] animated:animated];}
viewWillAppear執行完成後,系統會調用[tableView reloadData]方法(在showModel方法中調用),對tableView進行更新。調用TTTableViewDataSource或子類的- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section,- (UITableViewCell*)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法
//通常在客戶代碼中進行調用,形式如self.dataSource = ...- (void)setDataSource:(id<TTTableViewDataSource>)dataSource { if (dataSource != _dataSource) { [_dataSource release]; _dataSource = [dataSource retain]; _tableView.dataSource = nil;//此處是調用從基類繼承的setModel:方法 self.model = dataSource.model; }}
//在updateViewState中進行調用- (void)showModel:(BOOL)show { [self hideMenu:YES]; if (show) { //設定tableView的delegate [self updateTableDelegate]; _tableView.dataSource = _dataSource; } else { _tableView.dataSource = nil; } //在處理完成後,對tableView進行重新載入 [_tableView reloadData];}
- (void)updateTableDelegate { if (!_tableView.delegate) { [_tableDelegate release]; //建立tableView的delegate,預設情況下建立的是TTTableViewDelegate的執行個體 //如果TTTableViewDelegate無法滿足要求,客戶可以建立一個類繼承自TTTableViewDelegate並重寫createDelegate方法,建立自訂的TTTableViewDelegate子類 _tableDelegate = [[self createDelegate] retain]; // You need to set it to nil before changing it or it won't have any effect _tableView.delegate = nil; _tableView.delegate = _tableDelegate; }}
- (id<UITableViewDelegate>)createDelegate { if (_variableHeightRows) { return [[[TTTableViewVarHeightDelegate alloc] initWithController:self] autorelease]; } else { return [[[TTTableViewDelegate alloc] initWithController:self] autorelease]; }}
- (void)didLoadModel:(BOOL)firstTime { [super didLoadModel:firstTime]; //調用資料來源的tableViewDidLoadModel代理方法 [_dataSource tableViewDidLoadModel:_tableView];}
TTModelViewController
一個view controller用於管理附加在view上的一個model
- (void)viewWillAppear:(BOOL)animated { _isViewAppearing = YES; _hasViewAppeared = YES; [self updateView]; [super viewWillAppear:animated];}
- (void)updateView { if (_flags.isViewInvalid && !_flags.isViewSuspended && !_flags.isUpdatingView) { _flags.isUpdatingView = YES; // Ensure the model is created self.model; // Ensure the view is created self.view; [self updateViewStates]; if (_frozenState && _flags.isShowingModel) { [self restoreView:_frozenState]; TT_RELEASE_SAFELY(_frozenState); } _flags.isViewInvalid = NO; _flags.isUpdatingView = NO; [self reloadIfNeeded]; }}
- (id<TTModel>)model { if (!_model) { if (![TTNavigator navigator].isDelayed) { //createModel是個虛方法,用於客戶重寫以定義自已的model [self createModel]; } if (!_model) { [self createInterstitialModel]; } } return _model;}
- (void)setModel:(id<TTModel>)model { if (_model != model) { [_model.delegates removeObject:self]; [_model release]; _model = [model retain]; [_model.delegates addObject:self]; TT_RELEASE_SAFELY(_modelError); if (_model) { _flags.isModelWillLoadInvalid = NO; _flags.isModelDidLoadInvalid = NO; _flags.isModelDidLoadFirstTimeInvalid = NO; _flags.isModelDidShowFirstTimeInvalid = YES; } [self refresh]; }}
- (void)refresh { _flags.isViewInvalid = YES; _flags.isModelDidRefreshInvalid = YES; //執行“return _model ? _model : self”時,返回的是TTTableViewDataSource的執行個體 //下面的兩條語句會執行TTTableViewDataSource的isLoading和isLoaded方法 BOOL loading = self.model.isLoading; BOOL loaded = self.model.isLoaded; if (!loading && !loaded && [self shouldLoad]) { [self.model load:TTURLRequestCachePolicyDefault more:NO]; } else if (!loading && loaded && [self shouldReload]) { [self.model load:TTURLRequestCachePolicyNetwork more:NO]; } else if (!loading && [self shouldLoadMore]) { [self.model load:TTURLRequestCachePolicyDefault more:YES]; } else { _flags.isModelDidLoadInvalid = YES; if (_isViewAppearing) { //此處還會調用一次updateView方法,但在無異常時不會執行if語句中的內容 [self updateView]; } }}
//更新視圖的狀態- (void)updateViewStates { ... //前面的代碼主要是對視圖的狀態進行判斷,還有調用子類重寫的代理方法如didLoadModel:,還不是太懂 if (showModel) { //showModel和didShowModel方法都是虛方法,用於子類重寫 //此處會調用TTTableViewController中相關方法 [self showModel:YES]; [self didShowModel:_flags.isModelDidShowFirstTimeInvalid]; _flags.isModelDidShowFirstTimeInvalid = NO; } if (showEmpty) { [self showEmpty:YES]; } if (showError) { [self showError:YES]; } if (showLoading) { [self showLoading:YES]; }}
自到updateViewStates方法調用結果,TTModelViewController的viewWillAppear方法才調用結束,並回到TTTableViewController的viewWillAppear方法中
建立類
- (void)createModel {//設定tableView對應的dataSource self.dataSource = [TTListDataSource dataSourceWithObjects: [TTTableTextItem itemWithText:@"date" URL:@"tt://dateSelect"], nil];}
TTTableViewDataSource
- (id<TTModel>)model { return _model ? _model : self;}
- (BOOL)isLoaded { return NO;}
- (BOOL)isLoading { return YES;}