当从互联网获取表的数据时,有人可以用 UItableview 来解释 MVC 吗?

2023-11-27

任何人都可以向我解释 MVC 在 UITableView 方面如何工作,特别是从互联网获取数据时。

我很想知道 UItableview 的模型、视图和控制器是什么

我编写了以下 ViewController 代码,该代码从互联网获取数据并使用 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

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

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

有很多方法可以协调您的 Web 数据和表格视图,但我建议的一种方法是将您的 Web 服务调用重构为一个单独的商店类 - 比如说 iTunesStore - 让该类负责对服务进行调用并使用结果设置内部数组,它还应该能够返回行计数以及给定行索引的特定项目。

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

就像我说的,这是一个大问题,给你很多选择,但我已经给了你一些关于下一步该去哪里的考虑事项。

UPDATE
我添加了一些代码示例来帮助澄清。首先,我想明确表示,我不会提供完整的解决方案,因为这样做需要我对必要的实际解决方案做出太多假设——而且因为有几种不同的方法可以使用 AFNetworking 、网络服务等等……我不想陷入困境。 (例如在客户端缓存数据、后台任务和 GCD 等...)只是向您展示如何连接基础知识 - 但您肯定想学习如何在后台任务上使用 AFNetworking,请查看 Core Data或用于缓存的 NSCoding,以及其他一些正确执行此类操作的主题。

可以说,在适当的解决方案中:
- 您不想同步调用您的网络服务
- 您也不希望每次都重新请求相同的数据 - 即不要从服务重新下载相同的记录,除非它发生了变化
- 我不会在这里展示如何做这些事情,因为它超出了范围;查看下面的书籍推荐以及此链接以了解有关这些主题的想法Ray Wenderlich - 将核心数据与 Web 服务同步

对于您的数据服务代码,我将创建一个“store”类。 (帮自己一个忙,如果你还没有《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

我现在有一个“存储”对象单例,我可以用它来获取记录、返回给定记录并告诉我记录计数。现在我可以从视图控制器中移动很多执行此操作的逻辑。

现在我不需要在你的 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
}];

您的视图控制器数据源方法现在如下所示:

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

在 cellForRowAtIndexPath 内部 - 我还调用我的存储对象来获取正确的记录

 - (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。这种方法有利有弊。
  • 我还没有显示出这个应用程序所急需的任何真正的异步行为或缓存
  • 这确实展示了如何完成一些模型职责并分离一些表视图数据源问题。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当从互联网获取表的数据时,有人可以用 UItableview 来解释 MVC 吗? 的相关文章

  • 如何在 iPhone 中以编程方式访问保存的图像中的图像而不使用 UIimagePickerController?

    我知道如何让用户从 UIImagePickerController 选择图像 但我不想要那样 我只想将 NSArray 图像存储在手机中 但我不想让用户参与 选择一个然后拥有该图像 相反 我创建了自己的自定义图像选择器控制器并希望有画廊作为
  • 如何使用 Restkit 0.20.0 创建/发布新的托管对象到服务器?

    我很难找到创建新托管对象 设置其值以及使用 Restkit 保存到服务器的文档或示例 我有一篇 NSManagedObject 帖子 interface Post NSManagedObject property nonatomic ret
  • 监控Mac网络流量

    我想知道如何监控 Mac 上的网络流量 就像活动监视器的方式一样 显示进出的字节 数据包 我知道这有点模糊 但我不确定最好的起点 编辑 我想用代码来完成此操作 而不是使用现有的软件 我刚刚找到了开源项目 菜单表 http www ragin
  • 如何将 AdMob 广告添加到 UITableView

    我正在尝试将 AdMob 广告添加到表格视图中 我希望它出现在每 10 个单元格中 例如 如果您有 Reddit 应用程序的免费版本 就像它一样 我尝试遵循 AdMob 文档 但没有任何运气 而且我确信我遗漏了一些东西 任何人都可以阐明一种
  • 使用 Swift 导入 aurioTouch 库

    我正在尝试将 Objective C 应用程序转换为 swift 我想导入课程奥里奥触摸 https developer apple com library ios samplecode aurioTouch Introduction In
  • 使用 NSPredicate 来检测 NOT CONTAINS

    我放弃 我已经尝试了我能想象到的所有组合来检查一个字符串是否包含另一个字符串 这是描述我想要做的事情的直观语法示例 NSPredicate pPredicate NSPredicate predicateWithFormat NOT K C
  • 将箭头附加到 UIBezierPath

    我需要你的帮助 我正在尝试使用具有可变宽度的 UIBezierPaths 创建一个图形 并由带有两个控制点的贝塞尔曲线组成 现在我想在这些路径的末尾 右侧 添加箭头 有没有办法做到这一点 即通过附加一个包含三角形的较小线宽的子路径 这是我想
  • 加快 SpriteSheet 的 UIImage 创建速度

    我不确定我的标题是否正确 但我不确定我的问题到底在哪里 我需要从 spritesheet 加载 UIImage 数组 然后将其用作 UIImageView 中的动画 spritesheet是用TexturePacker生成的 它生成巨大的图
  • 使用自定义组件:子类 UIView 或 UIViewController?

    我正在研究 UISegmentedControl 的自定义实现 我想创建一个能够接收配置数据并从中获取类似于 UISegmentedControl 的自定义视图的组件 我开始对 UIView 进行子类化 我可以使用以下代码创建自定义 UIS
  • 在 Interface Builder 中启用/禁用 NSLayoutConstraints

    NSLayoutConstraint in iOS 8 0 has a BOOL属性称为active这使得动态禁用 启用所述布局约束变得容易 要为视图控制器创建第二个布局集 然后我可以以编程方式启用 禁用它 通过IBOutletCollec
  • UIFont fontWithName:仅限于每个系列加载 2 个变体

    这个问题与带有自定义字体的 UILabel 显示 错误 自定义字体 https stackoverflow com questions 4622956 uilabel with custom font displays wrong cust
  • 搜索结果中的 Swift 搜索结果控制器连接到另一个视图控制器

    Problem 我有一个表格视图 用户可以滚动查找某些内容或使用搜索栏 搜索栏不是使用 StoryBoard 创建的 我的观点有一个UISearchController处理搜索栏和搜索结果更新 我遇到的问题是 自从我SearchResult
  • 使用 Swift 创建 SKSpriteNode 子类

    我正在尝试创建作为 SKSpriteNode 子类的类 并且我想向其添加其他属性和函数 但在第一步中我遇到了错误 这是我的代码 import SpriteKit class Ball SKSpriteNode init super init
  • 语言混合:模型和视图

    考虑开发一个应用程序 其中模型将使用 C 使用 Boost 编写 视图将使用 Objective C 使用 Cocoa Touch 编写 哪里有一些示例展示了如何集成 C 和 Objective C 来开发 iPhone 应用程序 直接从源
  • 如何在 xcode 中从 nib 文件创建视图?

    我有以下代码来创建视图并将其放入滚动视图中以允许分页代码工作正常 但是我不能做的是从 nib 文件加载视图 换句话说 我想使用 initWithNibName 而不是 initWithFrame void createPageWithCol
  • UIButton 图像调整大小/缩放以适合

    我有一个非常严重的问题 我不知道如何解决 我正在对 UIButtons 框架进行动画处理 当我对其进行动画处理时 我希望按钮中的图像缩放到与按钮相同的大小 它无需在我的 iPhone 模拟器上执行任何操作即可运行 但是当我在 iPad 模拟
  • 如何查看iOS11屏幕录制是否开启?

    为了检测 iOS11 屏幕录制功能的开或关 我使用了 isCaptured 和 UIScreenCapturedDidChange 通知 当我第一次启动应用程序并在 iOS11 内置屏幕录制功能上时 它会通知选择器方法 值为 True 但是
  • 如何在 JSONKit 中 JSON 序列化 NSDate 字典

    我尝试使用 Jsonkit 和 Apple 的 JSON 序列化器 但没有成功 它不断破坏 geo 属性 该属性是 NSNumbers 的 nsarray Post p Post alloc init p uname mike p like
  • 在 HStack 中以正确的方式对齐两个 SwiftUI 文本视图

    我有一个包含两行的简单列表视图 每行包含两个文本视图 查看一和查看二 我想对齐每行中的最后一个标签 查看两个 以便名称标签领先对齐并保持对齐 无论字体大小如何 第一个标签 查看一个 也需要前导对齐 我尝试在第一个标签 查看一个 上设置最小框
  • 将蒙版图像作为 PNG 文件写入磁盘

    基本上 我从网络服务器下载图像 然后将它们缓存到磁盘上 但在这样做之前 我想屏蔽它们 我正在使用每个人似乎都指出的屏蔽代码 可以在这里找到 http iosdevelopertips com cocoa how to mask an ima

随机推荐