use*_*880 9 model-view-controller objective-c uitableview ios
任何人都可以向我解释一下,当谈到UITableView时,MVC是如何工作的,尤其是从互联网上获取数据时.
我想知道UItableview的模型,视图和控制器是什么
我编写了以下ViewController代码,该代码从Internet获取数据并使用AFNetworking框架将其显示在表中.
您能告诉我如何更改它并将其分为模型,视图和控制器.我还写了一个刷新类,我猜这是模型的一部分.你能告诉我我是如何做出改变并使其成为模型的一部分.
编辑:以下答案帮助我理解理论上的概念,有人可以帮助我相应地更改代码(通过编写一个关于如何调用数组到这个类并填充表的新类,因为我使用的是json解析器).我想实现它.而不只是从理论上理解它.
#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
Run Code Online (Sandbox Code Playgroud)
这是你要问的一个非常大的问题.但让我回答一下尽可能简单.
有很多方法可以协调您的Web数据和表视图,但我可能会建议将您的Web服务调用重构为一个单独的商店类 - 比如iTunesStore - 让该类负责调用服务并使用结果设置内部数组,它还应该能够返回行计数以及给定行索引的特定项.
然后,您可以让此类响应所需的表视图委托方法的调用.要考虑的其他事项,使其他类成为单例,使其符合UITableviewDatasource协议本身并将其指定为表视图的数据源.
就像我说的那样,一个很大的问题,有很多选择,但我已经给你一些事情要考虑下一步去哪里.
更新
我正在添加一些代码示例以帮助澄清.首先,我想明确表示我不打算提供整体解决方案,因为这样做需要我在必要的实际解决方案上假设太多 - 并且因为有几种不同的方法可以使用AFNetworking ,网络服务等....而且我不想被追踪到那个兔子洞.(例如在客户端上缓存数据,后台任务和GCD等等)只是向您展示如何连接基础知识 - 但您肯定想学习如何在后台任务中使用AFNetworking,查看核心数据或者用于缓存的NSCoding,以及其他一些正确执行此类操作的主题.
可以说,在适当的解决方案中:
- 您不希望同步调用您的Web服务
- 您也不希望每次都重新请求相同的数据 - 即不要重新下载相同的数据从服务中记录,除非它改变了
- 我没有在这里展示如何做这些事情,因为它超出了范围; 查看以下书籍推荐以及此链接以了解这些主题Ray Wenderlich - 使用Web服务同步Core Data
对于您的数据服务代码,我会创建一个"商店"类.(帮自己一个忙,如果你还没有它,请购买Big Nerd Ranch iOS书
.iOS编程第4版
以下是代码中的一小部分 - 由于我无法进入的原因,我无法通过我的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
Run Code Online (Sandbox Code Playgroud)
......并且实现看起来像:
// 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
Run Code Online (Sandbox Code Playgroud)
我现在有一个'store'对象单例我可以用来获取记录,返回给定记录并告诉我记录计数.现在我可以从viewcontroller中移动很多逻辑.
现在我不需要在VC viewDidLoad方法中执行此操作.理想情况下,您将在商店对象中使用异步方法来获取记录,并在加载记录后使用块来回调您.在块中,您重新加载记录.像'可能'这样的东西的签名:
[[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
}];
Run Code Online (Sandbox Code Playgroud)
您的视图控制器数据源方法现在看起来像:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection(NSInteger)section {
[[iTunesStore sharedStore] recordCount];
}
Run Code Online (Sandbox Code Playgroud)
在cellForRowAtIndexPath里面 - 我也调用我的商店对象来获取正确的记录
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ... get cell
// ... get record
NSDictionary* record = [[iTunesStore sharedStore] recordAtIndex:indexPath.row];
// ... configure cell]
return cell;
}
Run Code Online (Sandbox Code Playgroud)
这是它的要点.如上所述,其他事情可能是:
希望这有助于为您提供有关您可能探索的不同方向的一些想法.快乐的编码!
| 归档时间: |
|
| 查看次数: |
3160 次 |
| 最近记录: |