Objective-Cの継承を棒グラフアプリで理解しよう Part2.~drawRectで描く。具体的実装編~

前回:Objective-Cの継承を棒グラフアプリで理解しよう Part1.~継承を使おうと思うまでの考えと構造~

方針

具体的なクラス(たとえば、赤いグラフをつくろう、青いグラフをつくろう、みたいな)を想定し、その共通要素を考えてから抽象クラスをつくるというのが自然な流れになると思います。

今回の場合は複数の棒グラフ的なものをdrawRectで描きます。

赤いグラフ、青いグラフをつくってみて、
「あれ、ここの要素だけしか違わないんだったら、共通要素を取り出せる!」
みたいになるとよいです。

慣れてくるとはじめから高度に抽象的なクラスができる達人ももちろんいらっしゃると思いますが、
はじめは具体から抽象に考えていく、というのは変わらないと思います。


では、やっていきましょう。

最初の状態を確認

SingleViewApplication,ARCあり,Storyboardなしで作成、プロジェクト名は「BlogGraph」としました。

赤い棒グラフ、青い棒グラフともにUIViewのサブクラスとして作成(初期段階)

New File」の「Objective-C class」からUIViewを選択し、AgraphRedクラスを作成。
同じようにして、BgraphBlueクラスも作成。



すると、こんな感じになってますか?


drawRectで図形を描く

UIViewサブクラスでAgraphRedクラスとBgraphBlueクラスを作成しました。
最初の状態ではdrawRectメソッドはコメントアウトされていると思います。

なのでまずは複数行にわたっているコメントを消し、drawRectメソッドが使える状態にしてください

コメント部分を消した状態は以下のようになります。

#import "AgraphRed.h"

@implementation AgraphRed

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    // Drawing code
}

@end

BgraphBlueクラスについても同様にしてください。



では、まずAgraphRedクラスについて実装します。

AgraphRed.m

#import "AgraphRed.h"

@implementation AgraphRed

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = UIColor.clearColor; //背景を透明に。背景のImageViewが見えるようにするため
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    // Drawing code
    CGContextRef context = UIGraphicsGetCurrentContext();  // コンテキストを取得
    
    // グラフの色
    CGContextSetStrokeColorWithColor(context,UIColor.redColor.CGColor); //赤色
    
    
    // 線の太さを指定
    CGContextSetLineWidth(context, 10.0);  // 10ptに設定
    
    CGContextMoveToPoint(context, 50, 110);  // 始点、110は高さ
    CGContextAddLineToPoint(context, 200, 110); // 終点
    CGContextStrokePath(context);  // 描画
}


今回のテーマは「継承」で「drawRect」の解説ではないので、drawRectについては別をご参照ください。


BgraphBlueクラスを実装します。

BgraphBlue.m

#import "BgraphBlue.h"

@implementation BgraphBlue

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = UIColor.clearColor; //背景を透明に。背景のImageViewが見えるようにするため
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    // Drawing code
    CGContextRef context = UIGraphicsGetCurrentContext();  // コンテキストを取得
    
    // グラフの色
    CGContextSetStrokeColorWithColor(context,UIColor.blueColor.CGColor); //青色
    
    
    // 線の太さを指定
    CGContextSetLineWidth(context, 10.0);  // 10ptに設定
    
    CGContextMoveToPoint(context, 50, 160);  // 始点、160は高さ
    CGContextAddLineToPoint(context, 100, 160); // 終点
    CGContextStrokePath(context);  // 描画
}


@end

ViewControllerにaddSubviewしてUIViewをのっける

AgraphRedとBgraphBlueクラスのインスタンスをつくり、サイズはinitWithFrameでself.view.boundsを指定。

ViewController.m

#import "ViewController.h"
#import "AgraphRed.h"
#import "BgraphBlue.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    AgraphRed *ag = [[AgraphRed alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:ag];
    
    BgraphBlue *bg = [[BgraphBlue alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:bg];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end


そして、ViewController.xibにUIImageViewをはりつけて背景としておいてください。

実行してみると、できているはずです。


次回はこれを発展させて、抽象クラスをつくってみます!