从互联网获取表格的数据时,任何人都可以用UItableview来解释MVC吗?

任何人都可以向我解释如何MVC的工作,尤其是当从互联网上获取数据的UITableView。

我真的很想知道什么是模型,视图和控制器,当涉及到一个UItableview

我已经写了下面的ViewController代码来源于互联网的数据,并使用AFNetworking框架显示在一张桌子上。

你能告诉我如何改变这个,把它分成模型,视图和控制器。 我也写了一个刷新类,我猜测是模型的一部分。 你能告诉我,我是如何做出改变,并使之成为模型的一部分。

编辑:下面的答案帮助我理解theoritically概念,有人可以帮助我相应地更改代码(通过编写一个新的类如何调用数组到这个类,并填充表,因为我使用的JSONparsing器)。 我想实现它。 而不是仅仅理解它。

#import "ViewController.h" #import "AFNetworking.h" @implementation ViewController @synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView, movies = _movies; - (void)viewDidLoad { [super viewDidLoad]; // Setting Up Table View self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, self.view.bounds.size.height) style:UITableViewStylePlain]; self.tableView.dataSource = self; self.tableView.delegate = self; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.tableView.hidden = YES; [self.view addSubview:self.tableView]; // Setting Up Activity Indicator View self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; self.activityIndicatorView.hidesWhenStopped = YES; self.activityIndicatorView.center = self.view.center; [self.view addSubview:self.activityIndicatorView]; [self.activityIndicatorView startAnimating]; // Initializing Data Source self.movies = [[NSArray alloc] init]; NSURL *url = [[NSURL alloc] initWithString:@"http://itunes.apple.com/search?term=rocky&country=us&entity=movie"]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; [refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged]; [self.tableView addSubview:refreshControl]; [refreshControl endRefreshing]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { self.movies = [JSON objectForKey:@"results"]; [self.activityIndicatorView stopAnimating]; [self.tableView setHidden:NO]; [self.tableView reloadData]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo); }]; [operation start]; } - (void)refresh:(UIRefreshControl *)sender { NSURL *url = [[NSURL alloc] initWithString:@"http://itunes.apple.com/search?term=rambo&country=us&entity=movie"]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { self.movies = [JSON objectForKey:@"results"]; [self.activityIndicatorView stopAnimating]; [self.tableView setHidden:NO]; [self.tableView reloadData]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo); }]; [operation start]; [sender endRefreshing]; } - (void)viewDidUnload { [super viewDidUnload]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } // Table View Data Source Methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (self.movies && self.movies.count) { return self.movies.count; } else { return 0; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"Cell Identifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; } NSDictionary *movie = [self.movies objectAtIndex:indexPath.row]; cell.textLabel.text = [movie objectForKey:@"trackName"]; cell.detailTextLabel.text = [movie objectForKey:@"artistName"]; NSURL *url = [[NSURL alloc] initWithString:[movie objectForKey:@"artworkUrl100"]]; [cell.imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:@"placeholder"]]; return cell; } @end 

这是一个很大的问题,你问。 但让我尽可能简单地回答。

  • 模型 – 您的数据源; 最终它是您的Web服务数据
  • 控制器应该是拥有表视图的东西,并在视图上调解设置属性,并对视图中的事件作出反应,并根据需要对模型进行更改
  • 视图 – 您的表格视图和表格视图单元格的组合

有很多方法来协调您的networking数据和您的表视图,但我可能会build议将您的Web服务调用重构到一个单独的商店类 – 比如iTunesStore – 有这个类负责调用服务并设置一个内部数组的结果,它也应该能够返回一个行计数以及一个给定的行索引的特定项目。

然后,您可以让此类响应所需的表视图委托方法的调用。 其他的事情要考虑,使这个其他类单身,它符合UITableviewDatasource协议本身,并将其分配为表视图的数据源。

就像我说的,有一个很大的问题,有很多的select,但是我已经给了你一些事情来考虑下一步该怎么做。

UPDATE
我添加了一些代码示例来帮助澄清。 首先,我想表明,我不打算提供整体解决scheme,因为这样做需要我在必要的实际解决scheme上承担太多的责任 – 而且由于有几种不同的方法可以与AFNetworking ,networking服务等….我不想被追踪到那个兔子洞。 (比如在客户端上caching数据,后台任务和GCD等等)。只要向你展示如何连接基础知识 – 但是你一定要学习如何在后台任务中使用AFNetworking,查看Core Data或NSCoding进行caching,还有一些其他的主题正确地做这种事情。

只要说一个恰当的解决办法就足够了:
– 你不想同步调用你的Web服务
– 您也不希望每次重新请求相同的数据,即不要重新从服务中下载相同的logging,除非其更改
– 我不在这里展示如何做这些事情,因为它超出了范围; 看下面的书推荐以及这个链接,以获得这些主题的想法雷文德利 – 同步核心数据与Web服务

对于您的数据服务代码,我会创build一个“商店”类。 (自己帮忙,如果还没有的话,可以买一本Big Nerd Ranch iOS的书。
iOS编程第四版

采取以下代码与一粒盐 – 由于我无法进入的原因,我无法从我的Mac(在一台Win机器上)做到这一点,我也无法复制,甚至无法抄送自己的代码。 ..所以我正在做的所有在StackOverflow编辑器…

我的iTunesStore契约(头文件)看起来像这样:

 // iTunesStore.h #import <Foundation/Foundation.h> @interface iTunesStore : NSObject - (NSUInteger)recordCount; - (NSDictionary*)recordAtIndex:(NSUInteger)index; // could be a more specialized record class + (instancetype)sharedStore; // singleton @end 

…和实现将看起来像这样:

 // iTunesStore.m #import "iTunesStore.h" // class extension @interface iTunesStore() @property (nonatomic, strong) NSArray* records; @end @implementation iTunesStore -(id)init { self = [super init]; if(self) { // DO NOT DO IT THIS WAY IN PRODUCTION // ONLY FOR DIDACTIC PURPOSES - Read my other comments above [self loadRecords]; } return self; } - (NSUInteger)recordCount { return [self.records count]; } - (NSDictionary*)recordAtIndex:(NSUInteger)index { NSDictionary* record = self.records[index]; } -(void)loadRecords { // simulate loading records from service synchronously (ouch!) // in production this should use GCD or NSOperationQue to // load records asynchrononusly NSInteger recordCount = 10; NSMutableArray* tempRecords = [NSMutableArray arrayWithCapacity:recordCount]; // load some dummy records for(NSInteger index = 0; index < recordCount; index++) { NSDictionary* record = @{@"id": @(index), @"title":[NSString stringWithFormat:@"record %d", index]}; [tempRecords addObject:record]; } self.records = [tempRecords copy]; } // create singleton instance + (instancetype)sharedStore { static dispatch_once_t onceToken; static id _instance; dispatch_once(&onceToken, ^{ _instance = [[[self class] alloc] init]; }); return _instance; } @end 

我现在有一个“商店”对象单身我可以用来获取logging,返回给定的logging,也告诉我一个logging计数。 现在我可以从视图控制器移动很多逻辑。

现在我不需要在你的VC viewDidLoad方法中做这个。 理想情况下,您将在商店对象中使用asynchronous方法,以便在加载logging时获取logging和块以便回拨您。 在块内重新加载logging。 像这样的签名可能看起来像:

 [[iTunesStore sharedStore] loadRecordsWithCompletion:^(NSError* error){ ... if no error assume load records succeeded ... ensure we are on the correct thread [self.tableView reloadData]; // will cause table to reload cells }]; 

您的视图控制器数据源方法现在看起来像:

  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection(NSInteger)section { [[iTunesStore sharedStore] recordCount]; } 

在cellForRowAtIndexPath里面 – 我也调用我的存储对象来获取正确的logging

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // ... get cell // ... get record NSDictionary* record = [[iTunesStore sharedStore] recordAtIndex:indexPath.row]; // ... configure cell] return cell; } 

这是它的要点。 其他要做的事情,如上所述将是:

  • 让ITunesStore实现UITableViewDataSource,然后直接处理tableview数据源方法 – 如果你这样做,你不想让iTunesStore成为一个单例。 你可以设置一个iTunesStore的实例作为tableview的委托,而不是viewcontroller。 这样的做法有利有弊。
  • 我没有显示任何真正的asynchronous行为或caching这个应用程序哭了
  • 这确实显示了如何取消你的一些模型职责,并分离出一些tableview数据源的问题。

希望这将有助于给你一些关于你可能探索的不同方向的想法。 快乐的编码!

就UITableViewController而言,通常所有angular色模型,视图和控制器(MVC)都是由您的UITableViewController本身来播放的。 您的代码也是如此。

  1. 作为模型 – 它提供数据到你的表格视图。
  2. 作为控制器 – 它控制表的外观和感觉像行数,部分,高度和宽度等,供应数据从模型到表视图
  3. 作为视图 – 它的视图属性拥有UITableView

现在,要采用不同的方法,可以将Model从控制器类中分离出来。 对于NSObject有一个子类,并设置它可以由Controller使用的状态。

希望这对你有意义。