2014年4月24日木曜日

iOS4からのアニメーションはanimateWithDuration: が標準

いままで、Viewのアニメーションは、beginAnimations:を使ってたけど、なんとiOS4からは、ブロック構文をつかったanimateWithDurationが普通なのな。

なぜここに行き着いたかというと、アニメーションを2つ続けるとうまく動かない(並列動作してしまう)ため、もう少しうまく動かしたかったためです。

で、結果は次のコード。隠してからcompletionで表示すればいいということになります。

今ひとつ文法理解していないけど、こういうことですw


- (void)hideAndShow_hideView:(UIView *)hideView showView:(UIView *)showView{
    // アニメーションでビューを隠す
    self.view.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height-100, [[UIScreen mainScreen] bounds].size.width, 100);
    [UIView animateWithDuration:1.0f
                          delay:0.0f
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         self.view.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height-50, [[UIScreen mainScreen] bounds].size.width, 100);
                     }
                     completion:^(BOOL finished){
                         hideView.hidden = YES;
                         showView.hidden = NO;
                         [UIView animateWithDuration:1.0f
                                               delay:0.0f
                                             options:UIViewAnimationOptionCurveEaseInOut
                                          animations:^{
                                              self.view.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height-100, [[UIScreen mainScreen] bounds].size.width, 100);
                                          }
                                          completion:^(BOOL finished){
                                          }
                          ];
                     }
     ];

}

2014年4月22日火曜日

UITabbarControllerでTabbarItemが灰色で見えない

これ絶対ハマりません?

自分はXCodeが壊れたかとおもって、XCode再インストールまでしちゃいましたよ。ディスクユーティリティでアクセス権も治したし。ほんとかんべんしてほしい。

正解はどうやら、TabbarItemがCustumになっていることから来ているらしい。

しかも修正は飛び先のItemをCustumから他のものにした上でSegueを繋ぎ直すというなんともな仕様。どうにかしてほしいなう。

で無事灰色がなくなりました。っていうかググっても出てこなかったんですが、皆んな困ってないのかね。ま、いいけど。1日損したわ・・・

2014年4月20日日曜日

Wahoo Fitness API

Wahoo ハートレートモニターがやって来ました。

何故購入したかというと、甲状腺機能亢進のため心拍が高くなる傾向にあり、高いときには抑えるためにβ遮断薬を服用しなくてはならないからです。

1日3回飲めばいいのですが、忘れたり、規定通りの服用でもいいとも限らないので常時チェックしたい。

運動アプリでモニターすればいいのかもしれないですが、今ひとつ用途がちがうもので、自分で作ろうかしらん、という感じです。



APIドキュメントについては、XCode5以上ですとWebサイトにある方法ではドキュメントは入れられません。そのためには、WahooからもらえるSDKにある*.docsetを、Finderで「このMac」を選択したあと、右上で「DocSets」と検索してでてくるDocSetsフォルダに入れ込みます。XCode5を再起動し、Window-Documentation and API Referenceを選択するとWahoo APIのリファレンスが見れます(といってもWebサイトと変わりなさそうです)。



Wahoo Fitness APIは、WFHardwareConnector というクラスとして提供されます。WFHardwareConnectorはANT+ とBTLEセンサーの設定やデータ取得が可能です。

− 下準備

❏プロジェクトの設定
  プロジェクトのBuild SettingsのLinking セクションにあるOther Linker Flagsで、-lstdc++ -all_load  を設定します。

❏ターゲットの設定
  ターゲットのBuild PhasesにあるLink Binary With Librariesで+ボタンを押下し、Add Other... ボタンを押し、ダウンロードしたWahoo Fiitness APIにあるWFConnector.frameworkを選択する。さらにiOS標準のフレームワークのうち、ExternalAccessory.framework、CoreBluetooth.framework、libstdc++.dylib(iOS7 SDKの場合)を指定する。その際、CoreBluetooth.frameworkはOptionalを指定する。

❏アプリケーションバンドルの設定
 アクセサリ接続とバックグラウンド動作のため info.plistに次を設定する。
    Supported external accessory protocols  のitemにcom.momentumoftechnology.fisica 

    Required background modes のitemにexternal-accessory, と bluetooth-central 

注)prepareForBackground (WFHardwareConnector)がバックグラウンドモードと転送準備のためにリソースを初期設定する。しかしreturnFromBackground (WFHardwareConnectorと合わせて、iOS5.0以降ではこれらメソッドは不要。バックグラウンド操作では以下が必要。

さらにマニュアルにはありませんが、Wahoo Fitness APIではarm64がサポートされていません。そのため、プロジェクトのBuild SettingsのArchitecuresで、ArchitecuresをStandard(armv7,armv7s,arm64)からothersで、$(〜STANDARDS)とかを削除して、armv7とarmv7Sをそれぞれ+し(一緒にいれてはいけません)、Build Active Architecure OnlyをたぶんNO(かな?)、Vaild Architecures でarm64を削除します。

これでサンプルとかがコンパイルできるようになります。

2014年4月18日金曜日

Googleの広告デリゲートを別クラスにするには

Gooleの広告(AdMob)のデリゲートをrootViewControllerなんかにいれちゃうと、どうもソースコードがコテコテに油っこくなっちゃいます。

なので、adMob.delegate = selfってやつを、adMob.delegate = adViewController (そう、AdMobの場合、デリゲート先はViewController限定なのでした)なんてすると、どうもハングアップしてしまいます。

しかたないのでrootViewControllerにながながとAdMobのコードを入れ込みましたが、どうも気持ち悪い。


で、rootViewControllerで、どうにかしてadViewControllerを生成してなんとかならないか、いろいろググっても出てこない・・・

いろいろと試した結果、こんな感じで成功しました。

1.FileでViewControllerとしてAdViewController.h/.mを作っておく。

2.ストーリーボードでAdViewControllerをViewController部品をドラックしてきて作る。
 大きさはSizeをFreeformにして、320x50に指定(指定しても関係ないっぽいですが)。
 クラスはAdViewControllerにしておく。
 Storyboard内で繋げないので、Storyboard ID に"adViewController"とか名前をつけておく。

3.rootViewController内でStoryboard内のAdViewControllerのインスタンスを生成しAddViewする。
Storyboard内にAdViewControllerが定義済みなので、そいつを[self.storyboard instantiateViewControllerWithIdentifier:@"adViewController”];でインスタンス化してあげる。
ここがキモでした。

その上で、presentViewController「ではなく」、adViewControllerのビューをaddSubviewしてあげるのです。

#import "AdViewController.h"

@interface rootViewController ()
@property (nonatomic,strong) AdViewController * adVC;
@end

@implementation rootViewController

- (void)viewDidLoad {
[super viewDidLoad];
        
    _adVC = [self.storyboard instantiateViewControllerWithIdentifier:@"adViewController"];
    [self.view addSubview:_adVC.view];

@end

4.最後にAdViewControllerのviewDidLoad内に、self.viewのCGRectで、rootViewController内のView上の位置や、self.view内のAdMobのビューの位置を指定してあげたり、デリゲートをselfにしていろいろ書いてあげたりする。つまりAdMobの処理はAdViewController内に「全て」記載してあげればいい。それだけ。

いやぁ、悩みましたよ。それだけ。はい。

2014年4月17日木曜日

Objective-Cのオブジェクト間のメッセージとデータの共有

オブジェクト指向の場合、いろいろとオブジェクトを分割してはじめてその威力を発揮する。

しかしその場合は、オブジェクトからオブジェクトにイベントとデータを送り、連携しなくてはならない。

その連携の方法の基本は以下の3つに分類できる。

・生成元のオブジェクトから生成先のオブジェクトへのメッセージは、メソッド呼び出し
・その逆はデリゲートとなる。
・任意のオブジェクト間のメッセージは通知(Notification)となる。

やっとわかったよw

あとは、オブジェクト間のデータ共有はこれだ(多分)。
以下ではClassAとClassBとの間でvatModeを共有する。共有は非常に楽ちんだ。

ただしイベントは飛ばないので値の変更通知が必要な場合は上の3つを使うことになる。


なお、プロパティは循環参照にならないので、どのクラスでもStrongでいいらしい。ひとつ賢くなったかなう?

-------SharedValue.h------
‪#‎import‬ <Foundation/Foundation.h>
@interface SharedValue : NSObject
+(id)sharedAllocation;
@property (nonatomic, strong) NSString *vatMode;
@end
-------SharedValue.m------
#import "SharedValue.h"
@implementation SharedValue
static id allocatedInstance = nil;
+(id)sharedAllocation{
if (allocatedInstance == nil) {
allocatedInstance = [[self alloc]init];
}
return allocatedInstance;
}
//--- shared value----------
-(NSString *)vatMode{
if(!_vatMode) _vatMode = [[NSString alloc]init];
return _vatMode;
}
@end
------------------------------------
------ ClassA.m --------------
#import "SharedValue.h"
@interface ClassA ()
@property (nonatomic, strong) SharedValue *sharedValue;
@end
@implementation ClassA
-(id)init {
self = [super init]
if (self) {
_sharedValue = [SharedValue sharedAllocation];
_sharedValue.vatMode = @"ClassA";
}
return self;
}
@end
------ ClassB.m ------------
#import "SharedValue.h"
@interface ClassA ()
@property (nonatomic, weak strong) SharedValue *sharedValue;
@end
@implementation ClassV
-(id)init {
self = [super init]
if (self) {
_sharedValue = [SharedValue sharedAllocation];
_sharedValue.vatMode = @"ClassB";
}
return self;
}
@end
------------------------------------

2014年4月15日火曜日

Storyboard で UITableViewController にツールバーをつけるには

StoryboardでStaticCellを使うにはUITableViewControllerを使う必要があります。

UITableViewControllerをつかってみると、なんとUITableViewがフルスクリーンになったまま、ほかの部品を入れようとしても、テーブル内の部品になり、CancelボタンやDoneボタンを入れ込むことができません。

が、しかし、出来ることがわかりました。


なんと、UIViw部品をUITableView部品の上にねじ込めば(ドラッグすれば)よかっただけなんですよね・・・わからんよ。ガイドしてくれよ・・はぁ、半日悩んだわ・・・

あとNavigationコントローラつけずSegueでpushすることはできないんですが、それもわからんかった。Navigationコントローラつけないんだったら、Modale一択ね。そう言ってくれよ・・ほんと疲れるわ。で完成。


2014年3月18日火曜日

UIViewControllerとUITableViewControllerの違い

TableView生成時にself.viewに合わせてframeを生成しない/する

reloadDataでTableViewの行を変更できる/できない。UITableViewController意味あんのかよ。

tavleView.rowHeightが有効か、有効でないか。ってさ、UITableViewController終わりにしてほしいなう。

わかるまで1週間かかったよ。まったく!

(追記)=> Static cell(ストーリーボード上で見た目編集できるもの)を使うにはUITableViewController必須のようです。UITableViewControllerが使えるのは機能はこれくらいかな?