-
Notifications
You must be signed in to change notification settings - Fork 336
9.2 クラス設計 2
引き続きクラス設計について説明します。
9.1 で例として挙げた仕様がありました。
- ファーストビューので、曜日ごとに違う画像を表示したい
- その画像をタップした際の画面遷移やアクションが画像によってことなる
この仕様が画像では無く、様々な種類のビューをオーバーレイし、×ボタンを押すと閉じることが出来るように変更したいとします。
この場合は、一つのカスタムビュークラスでテキストビューやイメージビューなどのサブビューを条件分岐で表示非表示にしがちです。しかし、そうしてしまうとコードにレイアウトのコードが増えたり、ビューの種類が増えてきた場合に条件分岐がさらに多くなり対応が難しくなります。
こういったケースでは抽象クラスを使うと上記の問題は解決できます。
ポイント Objective-C では、抽象クラスを作成する言語的機能(Java の abstract 修飾子など)は存在しません。よって、抽象クラスとして作成したクラスのインスタンスも生成可能です。NSObject クラスのインスタンスが生成可能なように、Objective-C では抽象クラスの扱いに関しては開発者側で行う必要があります。
上記の例では抽象クラスを作成し、そのサブクラスで適宜必要なコンポーネントとレイアウトの実装を行うと良いでしょう。
では実際に実装していきましょう。ここでは YES/NO のボタンを設置するカスタムビュー MixiDailyChoiceView を作成していきます。
抽象クラス MixiDailyView では xib ファイルは作成せず、.h .m ファイルだけ作成します。
ヘッダーでは、サブクラスの delegate method 全てを含めた delegate protocol を宣言しておきます。全てのサブクラスで実装する必要のある delegate method は @required で、サブクラスごとに実装が必要なものに関しては @optional にしておけば必要に応じて delegate 先で実装できます。
MixiDailyView.h
@protocol MixiDailyViewDelegate <NSObject>
@required
-(void)dailyViewDidPressCloseButton;
@optional
-(void)dailyViewDidPressYesButton;
-(void)dailyViewDidPressNoButton;
@end
@interface MixiDailyView : UIView
@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UIButton *closeButton;
@property (nonatomic, weak) IBOutlet UILabel *dateLabel;
@property (nonatomic, weak) id delegate;
+(MixiDailyView *)dailyView;
-(IBAction)pressCloseButton:(id)sender;
@end
MixiDailyView.m
#import "MixiDailyView.h"
@implementation MixiDailyView
-(void)pressCloseButton:(id)sender
{
if ([_delegate respondsToSelector:@selector(dailyViewDidPressCloseButton)]) {
[_delegate dailyViewDidPressCloseButton];
}
}
@end
実装クラスである MixiDailyChoiceView では .h, .m に加えて .xib まで作成して実装します。
MixiDailyChoiceView.h
#import "MixiDailyView.h"
@interface MixiDailyChoiceView : MixiDailyView
- (IBAction)pressYesButton:(id)sender;
- (IBAction)pressNoButton:(id)sender;
@end
MixiDailyChoiceView.m
#import "MixiDailyChoiceView.h"
@implementation MixiDailyChoiceView
+(MixiDailyView *)dailyView
{
NSArray *topLevelViews = [[NSBundle mainBundle] loadNibNamed:@"MixiDailyChoiceView"
owner:self
options:nil];
MixiDailyChoiceView *dailyChoiceView = topLevelViews[0];
return dailyChoiceView;
}
- (IBAction)pressYesButton:(id)sender
{
if([self.delegate respondsToSelector:@selector(dailyViewDidPressYesButton)]){
[self.delegate dailyViewDidPressYesButton];
}
}
- (IBAction)pressNoButton:(id)sender
{
if([self.delegate respondsToSelector:@selector(dailyViewDidPressNoButton)]){
[self.delegate dailyViewDidPressNoButton];
}
}
@end
MixiDailyChoiceView.xib
インスタンスを生成して表示させてみましょう。
MixiViewController.h
#import <UIKit/UIKit.h>
#import "MixiDailyChoiceView.h"
@interface MixiViewController : UIViewController<MixiDailyViewDelegate>
@end
MixiViewController.m
#import "MixiViewController.h"
@interface MixiViewController ()
@property (nonatomic, strong) MixiDailyView *dailyView;
@end
@implementation MixiViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_dailyView = [MixiDailyChoiceView dailyView];
_dailyView.center = self.view.center;
_dailyView.delegate = self;
[self.view addSubview:_dailyView];
}
-(void)dailyViewDidPressCloseButton
{
[_dailyView removeFromSuperview];
}
-(void)dailyViewDidPressYesButton
{
//do something
NSLog(@"Yes");
}
-(void)dailyViewDidPressNoButton
{
//do something
NSLog(@"No");
}
@end
アプリケーション内で一つだけインスタンスを存在させたい場合、Singlton パターンを使って実装します。Cocoa API では [NSUserDefaults standerdDefaults] [NSNotificationCenter defaultCenter] などで実現されています。その実装方法は以下のようになります。
MixiSharedObject.h
#import <Foundation/Foundation.h>
@interface MixiSharedObject : NSObject
+(MixiSharedObject *)sharedInstance;
-(void)doSomthing;
@end
MixiSharedObject.m
#import "MixiSharedObject.h"
@implementation MixiSharedObject
+(MixiSharedObject *)sharedInstance
{
static MixiSharedObject *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[MixiSharedObject alloc] init];
});
return sharedInstance;
}
-(void)doSomthing
{
//doSomething
}
@end
この実装により、どこからインスタンス生成を行ってもアプリケーション上では一つのインスタンスしか存在しないようになります。 試しにインスタンス生成を複数回行ったとします。
_array = [NSMutableArray array];
for (NSInteger i = 0; i < 10; i++) {
[_array addObject:[MixiSharedObject sharedInstance]];
}
instruments で allocation を見るてもインスタンスが一つだけ存在していることが分かります。(instruments に関しては 10 章で解説します)
はじめに
-
導入
-
1.3 UIViewController1 UIViewController のカスタマイズ(xib, autoresizing)
-
UIKit 1 - container, rotate-
-
UIKit 2- UIView -
-
UIKit 3 - table view -
-
UIKit 4 - image and text -
-
ネットワーク処理
-
ローカルキャッシュと通知
-
Blocks, GCD
-
設計とデザインパターン
-
開発ツール
-
テスト
-
In-App Purchase
-
付録