2014年4月17日木曜日

[iOS][Objective-C]StackとQueue(簡易実装)


どうも。

ずいぶんとご無沙汰しました…。
ごぶさたした理由はいろいろありますが、
書くと長いのでw

で、
今回のお題は、
StackとQueueについて。

Javaには、
java.util.Stackとかjava.util.Queueとかあって、
普通に使えるワケですが、
Objective-Cにはそんなのない…。

StackやQueueというのはデータ構造であって、
その仕組みが分かっていれば、
NSMutableArrayに対して、
相応の処理をしてやればいいだけ。

とは言え、
popとかpushと書いて、
イメージ通りに動く方が見た目にもスッキリなので、
予め実装しておく。

NSMutableArrayを使うのであれば、
カテゴリにしてしまうのが楽ですね☆

カテゴリ名は、
VirtualStack, VirtualQueueとでもしておきます。
Virtualなんてつけるほどすごいことでもないけどw

[NSMutableArray+VirtualStack.m]

#import "NSMutableArray+VirtualStack.h"

@implementation NSMutableArray (VirtualStack)

- (id)pop {

    id lastObj = [self lastObject];
 
    if (lastObj != nil) {
     
        [self removeLastObject];
    }
 
    return lastObj;
}

- (void)push:(id)obj {
 
    [self addObject:obj];
}

@end

[NSMutableArray+VirtualQueue.m]

#import "NSMutableArray+VirtualQueue.h"

@implementation NSMutableArray (VirtualQueue)

- (id)dequeue {
 
    id headObj = [self objectAtIndex:0];
 
    if (headObj != nil) {
     
        [self removeObjectAtIndex:0];
    }
 
    return headObj;
}

- (void)enqueue:(id)obj {
 
    [self addObject:obj];
}

@end

と、
ここまで書いておいて…。
これって、
StackもQueueも両方あったら、
Stackとしてpush-popしてきたものに対して、
いきなりdequeueとか出来ちゃったりするw

それぞれ、
NSMutableArrayをメンバーに持つ、
別なクラスに切り出した方がいいのかもしれない。
複数人開発や、
マルチスレッドでのアクセスがありうるとか、
そういうリスク管理の観点では、
クラスとしてきちんと区別した方がいい。

あくまで、
簡易的に実現するなら、
という方法ですね、これは。


それでは。
ちゃお☆


まこぴー。

2014年4月3日木曜日

[iOS][Objective-C]UIの表示位置やサイズを変更する


どうも。

実際の業務となると、
UIの表示位置やサイズを変更することが、
ちょいちょいとあります。

aViewというUIView*があって、
Y位置を100, 高さを100にしたいとすると…。

aView.frame.origin.y = 100.0f;
aView.frame.size.height = 100.0f;

としてやれるなら簡単ですが、
上記はできません…。

X, Y, Width, Heightのどれかをひとつだけでも変えたい場合でも、
やれることは、
[aView setFrame:xxxx];
だけである。

従って、
新しいCGRectを作ってやって、
そのCGRectをsetFrameしてやるしかない…。
上記の例だと、
XとWidthが変わらないから、
まずは元の位置をベースにしてCGRectを取得し、
YとHeightを変更。
そのCGRectをsetFrameする。

CCRect newFrm = aView.frame;
newFrm.origin.y = 100.0f;
newFrm.size.height = 100.0f;

[aView setFrame:newFrm];

ひとつの部品が1回動くだけならいいけど、
いくつかの部品を相関関係も気にしながら動かさなきゃいけないことの方が多い。
そうなると、
上記のようなコードをたくさん書かねばならず、
可読性やメンテナンス性が大きく損なわれる。

ので、
UIViewのカテゴリにしてしまう。
UIButtonとかUISwitchとか、
その辺も軒並みUIViewを継承しているので、
全般的に使える。

例のごとく、
カテゴリ名はとりあえずAddition…。
ソースはちょっと分量が多いのでヘッダのみ。
実装は上記のようなコードを書いて、
さらに内部でコールしているに過ぎない。

#import <UIKit/UIKit.h>

@interface UIView (Addition)

#pragma mark - Setters of X, Y, Width, Height
#pragma mark (with one parameter)
- (void)setX:(CGFloat)x;
- (void)setY:(CGFloat)y;
- (void)setW:(CGFloat)w;
- (void)setH:(CGFloat)h;
#pragma mark (with two parameters)
- (void)setX:(CGFloat)x Y:(CGFloat)y;
- (void)setX:(CGFloat)x W:(CGFloat)w;
- (void)setY:(CGFloat)y H:(CGFloat)h;
- (void)setW:(CGFloat)w H:(CGFloat)h;
#pragma mark (with all parameters)
- (void)setX:(CGFloat)x Y:(CGFloat)y W:(CGFloat)w H:(CGFloat)h;
#pragma mark (with CGPoint, CGSize)
- (void)setPoint:(CGPoint)p;
- (void)setSize:(CGSize)s;

#pragma mark - Calculation of X, Y, Width, Height
#pragma mark (of X)
- (void)xPlus:(CGFloat)f;
- (void)xMinus:(CGFloat)f;
#pragma mark (of Y)
- (void)yPlus:(CGFloat)f;
- (void)yMinus:(CGFloat)f;
#pragma mark (of Width)
- (void)wPlus:(CGFloat)f;
- (void)wMinus:(CGFloat)f;
#pragma mark (of Height)
- (void)hPlus:(CGFloat)f;
- (void)hMinus:(CGFloat)f;

@end

経験上、
これだけ実装しておけば、
あまり困らないハズ。
とにかく1ステップで位置/サイズ調整が終わるのは、
ソースコードの可読性に歴然と差が出る。
と思う。

それでは。
ちゃお☆


まこぴー。

2014年4月2日水曜日

[iOS][Objective-C]Storyboardの分割



どうも。

未だにStoryboardっつーのが、
よくわからないw
過去のプロジェクトではxibばかり扱ってきたので…。

で、
今のプロジェクトになってようやく、
Storyboardを使っているワケです。

最終的には担当者が自分ひとりになってしまったけど、
最初は3人いて、
ひとつのStoryboardを3人でいじってマージをするという、
悲惨な状況でしたw

根本的に、
xibにせよStoryboardにせよ、
実態はXMLなので、
XMLベースでマージをすればいいんですが、
まぁ大変です。

しかも、
後から画面を付け加えて、
pushViewControllerとかできなかったりして、
直感的なようで直感的でないし、
よくわからない…。

Storyboardをイメージでしか理解していなかったので、
複数人開発には向かないなぁ…。
なんて思っていました。

結局時間もなくて根本改善ができなかったのですが、
個人的にはひとつの答えに行き着きました。

Storyboardを最初から分割すればいいのでは…。
そして、
Push-Pop型の画面遷移の場合、
RootのViewControllerがいるワケで、
そいつからの流れでどんどんPushしてやれば、
Storyboardの見た目上でつながりを持っていなくてもいいのでは…?

で、
Root-Sub1-Sub2-Sub3
と、
それぞれ別のStoryboardにして、
・順番にPushしていって順番にPopできるか?
・popToRootViewControllerできるか?
換言すると、
NavigationControllerによるスタック管理がきちんと成り立つのか?
を検証してみたところ、
オールOK!
期待通りの結果が得られた。

まぁ、
Segueとかいうのを使ってつなげて、
ひとつのStoryboardで全画面をマッピングできるし、
ソースコード量が減らせる。
というのがStoryboardを使う醍醐味のひとつな気もしますがw



それでは。
ちゃお☆


まこぴー。

2014年4月1日火曜日

[iOS][Objective-C]ネット接続の確認


どうも。

Webサービスと連携していると、
ネット接続していることが必須ですね。
当たり前ですがw

先回りしてネット接続を確認して、
あらかじめアラートを出したり、
そもそも処理をさせないようにするとか。

そんなときは、
Reachability
というのが、
iOS Developer Libraryに転がっているので、
そいつを取り込んで使えばいい。
(Reachability.hとReachability.m)

確認の都度、
ごにょごにょと書くのは面倒なので、
utilみたいなクラスに、
クラスメソッドで定義しておく。

+ (BOOL)isAvailableDataNetwork {
 
    Reachability *internetReachability = [Reachability reachabilityForInternetConnection];
 
    NetworkStatus netStatus = [internetReachability currentReachabilityStatus];
 
    if (netStatus != NotReachable) {
     
        return YES;
     
    } else {
     
        return NO;
    }
}

netStatusは、

typedef enum : NSInteger {
    NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;

となっていて、
ViaWWANが3Gとかの接続です。


それでは。
ちゃお☆


まこぴー。