[Obj-C] JSONデータをモデルクラスを介して画面に表示する(後編)

前回のふりかえり

前編では、果物の名前と写真を表示するサンプルプログラムの作成を開始し、モデルクラスの作成を進めました。

後編では、JSONデータの読み取り、モデルクラスのインスタンスを複数持つ配列の作成、そして画面表示などを進めます。

JSONファイルを用意

JSONファイルを用意しましょう。今回はシンプルに3種類の果物データを用意しています。また、画像リソースファイルとして、apple.png, orange.png, banana.png をプロジェクトに追加しています。

Fruits.json

[
  {
  	"name":"りんご",
  	"image":"apple",
  },
  {
  	"name":"オレンジ",
  	"image":"orange",
  },
  {
  	"name":"バナナ",
  	"image":"banana",
  }
]

FruitService クラスを作成する

このクラスの役割は、以下のとおりです

  • JSONからデータを読み取る
  • Fruit型のデータ配列を返す

早速作っていきましょう。

ヘッダファイル

#import <Foundation/Foundation.h>

@interface FruitService : NSObject
- (NSArray *)readFruits;
@end

NSArray型の返り値を持つ、readFruits メソッドを宣言しています。

実装ファイル

#import "FruitService.h"
#import "Fruit.h"

@implementation FruitService

- (NSArray *)readFruits
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Fruits" ofType:@"json"];
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
    NSData *data = [fileHandle readDataToEndOfFile];
    
    id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    
    if (!]) {
        return nil;
    }
    
    NSMutableArray *fruitsArray = [NSMutableArray new];
    
    for (NSDictionary *dic in json) {
        Fruit *fruit = [[Fruit alloc] initWithDictionary:dic];
        [fruitsArray addObject:fruit];
    }
    
    return [fruitsArray copy];
}

@end

Fruits.json から読み取ったデータを、一旦 NSData型のデータとして変換します。その後、NSJSONSerialization クラスを用いてデータを オブジェクトの配列に変換しています。

そうしたオブジェクトをFruit型に変換し、複数の Fruit をまとめて配列として返しています。

StoryBoardの実装

スクリーンショット 2015-05-21 17.47.40

果物の名前、画像(UIImageView)、次の果物を表示するためのボタンがあります。

ViewControllerの実装

ヘッダファイル

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

実装ファイル

#import "ViewController.h"
#import "Fruit.h"
#import "FruitService.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *nameLabel;

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@property (nonatomic) NSArray *fruitsArray;

@property (nonatomic) NSInteger currentFruitNumber;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    FruitService *fruitsService = [FruitService new];
    self.fruitsArray = [fruitsService readFruits];
    [self showFruitInformation];
}

- (IBAction)tapNextButton:(id)sender
{
    if (self.currentFruitNumber < self.fruitsArray.count - 1) {
        self.currentFruitNumber ++;
    } else {
        self.currentFruitNumber = 0;
    }
    
    [self showFruitInformation];
}

- (void)showFruitInformation
{
    Fruit *fruit = self.fruitsArray[self.currentFruitNumber];
    self.nameLabel.text = fruit.name;
    self.imageView.image = [UIImage imageNamed:fruit.image];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

@end

[/code]

<p>詳細を見ていきましょう。</p>

<h4>プロパティ</h4>

<p><tt>tapNextButton</tt>では、ボタンを押すごとに、<tt>currentFruitNumber</tt>(現在の表示番号)を変化させ、画面表示を更新しています。</p>



<h4>showFruitInformation</h4>


- (void)showFruitInformation
{
    Fruit *fruit = self.fruitsArray[self.currentFruitNumber];
    self.nameLabel.text = fruit.name;
    self.imageView.image = [UIImage imageNamed:fruit.image];
}

showFruitInformationでは、fruitsArray の中から、1つの Fruit を取り出しています。

さらに、Fruit のプロパティである、name(果物名)とimage(画像名)を取り出し、画面に反映させています。

実行してみる

iOS Simulator Screen Shot 2015.05.21 18.20.36

iOS Simulator Screen Shot 2015.05.21 18.20.38

iOS Simulator Screen Shot 2015.05.21 18.20.39

Next ボタンをタップするごとに、表示が切り替わります。 お疲れ様でした!

クレジット

本記事中の画像はCC BY-SA 2.0より提供されています。

oranges macro by liz west

Apple by Joe King

going bananas : san francisco (2012) by torbakhopper