Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

9.1 クラス設計 1

Koya Tamura edited this page May 15, 2013 · 1 revision

Concepts in Objective-C Programming

Objective-Cプログラミングの概念

iOS アプリケーション開発は MVC フレームワークを採用しています。従って、我々が作成するカスタムクラスも MVC にのっとって開発する必要があります。

  • Model

  • View を構成する情報を保持

  • 必要に応じて、APIClient でリモートから情報を取得したり、DB にアクセスして情報を取得する

  • View

  • Model のデータを表示

  • ユーザから操作を受ける

  • Controller

  • Model と View を結びつけるもの

  • Model に更新メッセージを送り、Model からその完了通知を受ける

  • View に Model の情報を送り、View を通じてユーザからの操作を受ける

MVC Objective-Cプログラミングの概念 から引用

iOS の MVC フレームワークは上のような形をとります。View と Model を完全に切り離している理由は、View の再利用性を高めるためです。

各レイヤーで効率的に開発するためのポイントを解説します。

Model

複雑で大量な情報の取得、管理する必要がある Model は、Controller がそのデータにアクセスしやすいように設計する必要があります。

情報の取得するためのインタフェースを作成する

Model は Controller から情報取得のメッセージを受けられるようにします。そのメッセージを受けて Model はローカルやリモートから情報の取得を行います。従って Model ではローカルの情報へアクセスする処理や、HTTP クライアントを用いてリモートから情報を取得する実装をします。

Entity クラスで情報を管理する

取得してきた情報の各エントリは Entity クラスに定義し、そのインスタンスを Model に管理させるとよいでしょう。例えば Model クラスオブジェクトが API クライアントを用いて以下のような JSON を取得したとします。

[
  {
    "id" : "1FZ3P4ACUWBBC-2010061010321",
    "created_at" : "Thu Jun 10 01:32:13 +0000 2010",
    "text" : "つぶやきの本文",
    "user" : {
      "id" : "1FZ3P4ACUWBB",
      "screen_name" : "Becky",
      "profile_image_url" : "http://profile.img.mixi.jp/photo/user/1FZ3P4ACUWBBC_301280930.jpg",
      "url" : "http://mixi.jp/show_friend.pl?uid=1FZ3P4ACUWBB"
    },
    "reply_count" : "3",
    "favorite_count" : "5",
    "favorited" : true
  },
  ・・・
]

mixi Developer Center Voice API より引用

Model オブジェクトはレスポンスで取得したこの JSON をそのまま Array で管理するのではなく、各エントリごとに entity オブジェクトを生成して管理するします。以下は entity オブジェクトの例です。

MixiVoiceEntity.h

#import <Foundation/Foundation.h>

@interface MixiUserEntity : NSObject

@property (nonatomic, strong) NSString *profileImageURL;
@property (nonatomic, strong) NSString *URL;
@property (nonatomic, strong) NSString *userID;
@property (nonatomic, strong) NSString *screenName;

+(MixiUserEntity *)userEntitiWithDict:(NSDictionary *)dict;

@end

@interface MixiVoiceEntity : NSObject

@property (nonatomic, strong) NSString *voiceID;
@property (nonatomic, strong) NSString *createdAt;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, assign) NSInteger replyCount;
@property (nonatomic, assign) NSInteger favoriteCount;
@property (nonatomic, assign) BOOL favorited;
@property (nonatomic, strong) MixiUserEntity *userEntity;

+(MixiVoiceEntity *)voiceEntitiWithDict:(NSDictionary *)dict;

@end

Model オブジェクトはこの voiceEntity を配列で管理するようにします。そうすることで Controller 側でも参照しやすくなり、可読性も上がります。

View

Controller クラスファイル作成時にその xib ファイルも生成しましょう。Interface Builder を使うことで、Controller に view オブジェクト生成やレイアウトのコードを記述しなくてもよくなり可読性があがります。

また、3.* 系の研修で行った UIView またはそのサブクラスを作成し、独自の view component 作成すれば、あらゆる場面でその view の再利用が簡単に行えます。

Controller

Controller にはあらゆる処理が集中しがちです。コードが肥大化してくる多くは *ViewController.m です。

ロジック部分は極力別クラスに移す

Controller で if ~~~ else ~~~ という多くのロジックが入る可能性があります。例えば以下のような仕様があったとします。

  • ファーストビューので、曜日ごとに違う画像をオーバーレイしたい
  • その画像をタップした際の画面遷移やアクションが画像によってことなる

ここで考えられることは、

  • 今何曜日なのかを判定し、画像を生成して Controller が表示する
  • 各曜日ごとのイベントハンドラを実装し、画像のイベントを Controller が受け取る

これを全て Controller で実装すると確実に肥大化していきます。このような時はビジネスロジックを別クラスに移しましょう。

曜日を判定するカテゴリ

NSDate クラスのカテゴリとして作成すれば、任意の NSDate オブジェクトに対して曜日を求めることが出来ます。

NSDate+Day.h

typedef NS_ENUM(NSInteger, DayOfWeekType){
    DayOfWeekSunday = 1,
    DayOfWeekMonday,
    DayOfWeekTuseday,
    DayOfWeekWednesday,
    DayOfWeekThursday,
    DayOfWeekFriday,
    DayOfWeekSaturday
};

@interface NSDate (Day)

-(DayOfWeekType)dayOfWeekWithDate;

@end

NSDate+Day.m

@implementation NSDate (Day)

-(DayOfWeekType)dayOfWeekWithDate
{
    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *weekdayComponents = [gregorianCalendar components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:self];
    NSInteger day = [weekdayComponents weekday];
    return day;
}

@end

UIImageView インスタンスを生成する Factory クラス

MixiDailyImageViewCreator.h

#import "NSDate+Day.h"

@interface MixiDailyImageViewCreator : NSObject

+(id)imageViewWithDayOfWeek:(DayOfWeekType)dayOfWeekType;

@end

MixiDailyImageViewCreator.m

@implementation MixiDailyImageViewCreator

+(id)imageViewWithDayOfWeek:(DayOfWeekType)dayOfWeekType
{
    //do something
}

@end

画面遷移ロジックを別クラスで実装

イベントハンドラをすべて Controller で実装すると Controller が肥大化します。このようにイベントハンドラでいっぱいになってしまった場合、画面遷移を管理するクラスを生成し、Controller の参照を渡してそのクラスで処理を行うようにします。そうすると、Controller のコードの可読性は上がりますし、画面遷移の処理も一カ所にまとめることが可能になります。

MixiTransitionHandler.h

@interface MixiTransitionHandler : NSObject

+(void)pushSecoundViewControllerWithViewController:(UIViewController *)viewController;
+(void)pushThirdViewControllerWithViewController:(UIViewController *)viewController;
+(void)presentScountViewControllerWithViewController:(UIViewController *)viewController;
+(void)presentThirdViewControllerWithViewController:(UIViewController *)viewController;

@end

MixiTransitionHandler.m

@implementation MixiTransitionHandler

@implementation MixiTransitionHandler

+(void)pushSecoundViewControllerWithViewController:(UIViewController *)viewController
{
    UIViewController *vc = [[UIViewController alloc] init];
    [viewController.navigationController pushViewController:vc animated:YES];
}

+(void)pushThirdViewControllerWithViewController:(UIViewController *)viewController
{
    //do something
}
...

@end

はじめに

  1. iOSについて

  2. Xcode最初のステッフ

  3. 導入

  4. Objective C の基礎

  5. メモリ管理

  6. 1.3 UIViewController1 UIViewController のカスタマイズ(xib, autoresizing)

  7. 1.3 UIViewController1 UIViewController のカスタマイズ(storyboard)

  8. UIViewController2 - ModalViewController

  9. UIViewController2 - ModalViewController(storyboard)

  10. UIViewController3 - ライフサイクル

  11. HomeWork 1 Objective C の基本文法

  12. HomeWork 2 UIViewControllerとModalViewController

  13. HomeWork 3 UIViewController + Animation

  14. UIKit 1 - container, rotate-

  15. UINavigationController

  16. UITabController

  17. Custom Container View Controller

  18. Supporting Multiple Interface Orientations

  19. HomeWork 1 - タブバーからモーダルビューを表示する

  20. HomeWork 2 - NavigationController

  21. HomeWork 2.3 デバイスことに回転対応

  22. UIKit 2- UIView -

  23. UIView

  24. UIView のカスタマイズ

  25. UIView Animation

  26. HomeWork 1 - UIScrollView

  27. UIKit 3 - table view -

  28. UITableView について

  29. UITableViewとNavigationController

  30. custom UITableViewCell の作成

  31. UITableViewのその他のオプション、カスタマイズ

  32. HomeWork 1 - Dynamic height with a custom uitableviewcell

  33. UIKit 4 - image and text -

  34. UIImagePickerController

  35. Assets Library

  36. UITextFiled, UITextView

  37. KeyboardNotification

  38. Homework 1 - フォトの複数枚選択

  39. ネットワーク処理

  40. NSURLConnection

  41. JSONのシリアライズとデシリアライズ

  42. UIWebView

  43. ローカルキャッシュと通知

  44. NSUserDefaults, Settings Bundle

  45. NSFileManager

  46. Key Value Observing

  47. NSNotification、NSNotificationCenter を用いた通知

  48. UILocalNotification

  49. Blocks, GCD

  50. Blocks

  51. GCD

  52. 【演習】GCD,-Blocksを用いたHTTPリクエストマネージャの作成

  53. 設計とデザインパターン

  54. クラス設計 1

  55. クラス設計 2

  56. [クラス設計演習] (https://github.com/mixi-inc/iOSTraining/wiki/9.3-%E3%82%AF%E3%83%A9%E3%82%B9%E8%A8%AD%E8%A8%88%E6%BC%94%E7%BF%92)

  57. 開発ツール

  58. Instruments, デバッガ

  59. CocoaPods

  60. テスト

  61. iOS開発におけるテスト

  62. GHUnit

  63. Kiwi

  64. KIF

  65. In-App Purchase

  66. In-App Purchase

  67. 付録

  68. Tips of Xcode

  69. Auto Layout 入門

  70. Auto Layout ドリル

Edit sidebar

Clone this wiki locally