LoginSignup
3
3

More than 5 years have passed since last update.

【初学者向け】モデルクラスを作ってJSONをパースする

Last updated at Posted at 2016-08-19

はじめに

新人のコードレビューを行っていてどうやらモデルクラスを使ったJSONデータのパースができない、データベースからのクエリパースができない、みたいなことが多いので初学者向けに記事を書きます。

ここまでするか?っていうぐらいの半分ぐらいはします。

環境

  • Xcode 7.3.1
  • AFNetworking 3.0
  • OS X 10.11.6
  • CocoaPods 0.39.0

CocoaPodsは導入済み前提で進めます。

プロジェクト作成

スクリーンショット 2016-08-19 午後3.06.58.png

Xcodeを閉じておく

スクリーンショット 2016-08-19 午後4.18.55.png

閉じた!!かわいい!!

AFNetworkingインストール

$ cd /path/to/project/
$ pod init
$ vim Podfile
Podfile
target 'Sample' do
    pod 'AFNetworking', '~> 3.0'
end
$ pod install
$ open /path/to/project/project.xcworkspace/

使用するAPI

今回は東京都の天気を使用します。

サンプルコード

ATS関係で http にはアクセスできないのでInfo.plistに書き込みする

Info.plist
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
            <true/>
    </dict>

スクリーンショット 2016-08-19 午後3.25.25.png

Info.plistにkeyを上記のように追加しても良い

GETリクエスト

モデルわけするのがちょっと面倒なのでViewControllerに書いちゃいます。

ViewController.m
#import "ViewController.h"
#import <AFNetworking/AFNetworking.h>

@interface ViewController ()

@property (weak, nonatomic) NSMutableArray *weatherDatas;

@end

static NSString *const accessUrl = @"http://weather.livedoor.com/forecast/webservice/json/v1";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _weatherDatas = [NSMutableArray array];
    _weatherDatas = [self getWeatherInfoData];
}

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

- (NSMutableArray *)getWeatherInfoData {
    NSDictionary<NSString *, NSString *> *parameters = @{@"city" : @"130010"};
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager GET:accessUrl
      parameters:parameters
        progress:nil
         success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
             // ここに処理
         }
         failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
             NSLog(@"Error: %@", error);
         }
     ];
}

@end

モデルクラス作成

File > New > File... からファイルを作成します。
iOS内のSourceからCocoa Touch Classが選択されていたらNext

スクリーンショット 2016-08-19 午後3.34.42.png

スクリーンショット 2016-08-19 午後3.34.59.png

Weatherクラスを作りました。

今回は「 今日 」「 明日 」「 明後日 」のデータを取得するようにします。

Weather.h
#import <Foundation/Foundation.h>

@interface Weather : NSObject

@property (strong, nonatomic) NSString *dateLabel;
@property (strong, nonatomic) NSString *telop;
@property (strong, nonatomic) NSString *imageUrl;

@end

ざっとこんな感じにしておきましょう!

JSONデータパース

ViewController.mWeather.h をimportしましょう!
結構記事を作るのが面倒になってきたのでいろいろ端折りますが最終的には以下の様になればいいかな?って思います。

ViewController.m
#import "ViewController.h"
#import "Weather.h"
#import <AFNetworking/AFNetworking.h>

@interface ViewController ()

typedef void (^apiCallback)(NSMutableArray<Weather *> *weatherDatas);

@end

static NSString *const accessUrl = @"http://weather.livedoor.com/forecast/webservice/json/v1";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSDictionary<NSString *, NSString *> *parameters = @{@"city" : @"130010"};
    [self getWeatherInfoData:parameters callback:^(NSMutableArray<Weather *> *weatherDatas) {
        for (Weather *weather in weatherDatas) {
            NSLog(@"%@の天気は%@です。", weather.dateLabel, weather.telop);
        }
    }];
}

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

- (void)getWeatherInfoData:(NSDictionary<NSString *, NSString *> *)parameters callback:(apiCallback)callback {
    NSMutableArray *weatherDatas = [NSMutableArray new];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager GET:accessUrl
      parameters:parameters
        progress:nil
         success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
             for (NSDictionary<NSString *, NSString *> *forecasts in responseObject[@"forecasts"]) {
                 Weather *weather = [Weather new];
                 weather.dateLabel = forecasts[@"dateLabel"];
                 weather.telop = forecasts[@"telop"];
                 weather.imageUrl = [forecasts valueForKeyPath:@"image.url"];
                 [weatherDatas addObject:weather];
             }
             callback(weatherDatas);
         }
         failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
             NSLog(@"Error: %@", error);
             callback(nil);
         }
     ];
}

@end

NSLog自体はこんな感じででてきます!

NSLog出力結果
2016-08-19 16:09:18.008 Sample[57209:10708282] 今日の天気は曇時々晴です。
2016-08-19 16:09:18.008 Sample[57209:10708282] 明日の天気は曇時々雨です。
2016-08-19 16:09:18.008 Sample[57209:10708282] 明後日の天気は曇りです。

今回は画像をそのまま入れただけにしていますが、AFNetworkingを使って非同期で画像をキャッシュしつつ表示させるようにするのは以下のようにする

ViewController.m
#import <AFNetworking/UIImageView+AFNetworking.h>

[imageView setImageWithURL:[NSURL URLWithString:@"http://example.com/image.png"]
                      placeholderImage:[UIImage imageNamed:@"placeholder"]];

みたいにすると行けます

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3