ラベル Objective-C の投稿を表示しています。 すべての投稿を表示
ラベル Objective-C の投稿を表示しています。 すべての投稿を表示

2014年6月26日木曜日

CIFilterのちょっと気の利いた書き方

こんにちは。京都に生まれ育ってン十年。京都の暑さに身体が全く順応せず、毎年クールビズのシーズン間で夏バテしているmatsumiです。

今回のお題は「CIFilterのちょっと気の利いた書き方」です。

CIFilterとはCore Imageで用意されている画像にフィルターをかけるクラスです。
要は、写真系のアプリとかで使われている加工用のいい感じのフィルターを作れますよーってクラスです。
詳しくはAppleのクラスリファレンスあたりをお読みください。

このCIFilter、ちょっと書き方にくせがあって、その辺まとめてる記事があまり無かった気がしたので書いてみます。


まずは、試しにCIFilterで用意してあるフィルターの一種CIVignetteを使った結果です。
元画像
フィルター適用

ビネット効果(トンネルエフェクト)と呼ばれるもので、トイカメラ風の周囲が暗い画像を作る事ができます。

2014年4月4日金曜日

UIViewにCAGradientLayerを使ってグラデーションをかける

はじめまして。もうすぐ1年ですがピッチピチの新人と言い張るmatsumi(中年)です!

今回のお題は、iOS7がフラットデザイン風になったことで、
すっかり肩身の狭くなった感があるグラデーションについてです。

肩身が狭くなったとは言え、デザイン上なにかと必要になるグラデーションなのですが、
CAGradientLayer」を使用すればUIViewに簡単にグラデーションをかける事ができます。

手順は、
1.「CGGradientLayer」を作る
2.サイズ、色、開始位置と終了位置を指定
3.UIViewのlayerにグラデーションのレイヤーを追加
これだけ。

2013年5月31日金曜日

iphoneの課金処理を見通しよくする

objective-cには無名クラスが無い(たぶん)。
なのにだいたいインタフェースがオブザーバー。
その都度処理かえるのがめんどい。

ということでBlocksインタフェースをつけちゃいます。
今日はStoreKit。

目標

課金処理の見通しよくする

使う側をこんな感じに

課金処理で結局何がしたいかというと、
・課金をリクエストして成功したか失敗したか。
・リストアをリクエストして成功したか失敗したか

controller.m

// 購入処理
 SLSK* slsk = [SLSK getInstance];
 slsk.onFail = ^(NSError* error){
    NSLog(@"%@", error.debugDescription);
 };
 slsk.onPurchaseSuccess = ^(NSString* productIdentifier){
    NSLog(@"%@ 購入完了", productIdentifier);
 };
 [slsk puchase:@"com.subakolab.tyarintyariiiiiiin" /*productIdentifier*/];
// リストア
 SLSK* slsk = [SLSK getInstance];
 slsk.onFail = ^(NSError* error){
    NSLog(@"%@", error.debugDescription);
 };
 // リストア対象のアドオンの数だけ呼ばれる
 slsk.onRestoreSuccess = ^(NSString* productIdentifier){
    NSLog(@"リストアアドオン:%@", productIdentifier);
 };
 // リストアが全部終わったら呼ばれる
 slsk.onRestoreComplete = ^(){
    NSLog(@"リストア完了!");
 };

2013年1月23日水曜日

2つのModalViewを切り替えて表示する方法

ModalViewを起動している時に、一度ModalViewを閉じてすぐに他のModalViewを起動したい事があるかと思います。今回はその方法を書きます。
※iOS5以上での方法となります。

storyboard

まずstoryboardで起動元画面を1画面、ModalView用の2画面作成します。
左から以下の名前で進めていきます。
  • ViewController
  • ModalView1Controller
  • ModalView2Controller
ModalView2ControllerのStoryboardIDに「Modal2ViewController」と設定しておきます。

ModalView1Controller

1つ目のModalViewを実装していきます。
以下は ModalView1Controller.h
@protocol ModalView1ControllerDelegate
- (void)switchModalViewController:(UIViewController *)controller;
@end

@interface ModalView1Controller : UIViewController {
    id<ModalView1ControllerDelegate> myDelegate;
}

@property (nonatomic, retain) id myDelegate;
- (IBAction)showModalView2Controller:(id)sender; // storyboardに配置しているボタンのイベント
@end
次に ModalView1Controller.m
// 遷移するトリガー。ここではボタンクリックにしています
- (IBAction)showModalView2Controller:(id)sender
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil]; // MainStoryboard_iPhone.storyboard
    UINavigationController *nc = [storyboard instantiateViewControllerWithIdentifier:@"Modal2ViewController"]; // StoryboardIDを指定
    [myDelegate switchModalViewController:nc];
}
ここではDelegateを使って、遷移元に次に表示したいModalViewのControllerを渡している点がポイントです。

ViewController

次に1つ目の画面であるModalView起動画面を実装します。
以下は ViewController.m
// 遷移直前に呼ばれる
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    ModalViewController *controller = segue.destinationViewController;
    controller.myDelegate = self;

    // 上記はViewControllerに対して行う処理。Navigationとかは以下みたいにする
    // UINavigationController *navigationController = segue.destinationViewController;
    // MangaPageViewController *controller = (id)[[navigationController viewControllers] objectAtIndex:0];
}

#pragma mark - ModalView1ControllerDelegate
- (void)switchModalViewController:(UIViewController *)controller
{
    // 遷移先のModalViewを閉じて、次に表示させたいModalViewを起動
    [self dismissViewControllerAnimated:YES completion:^{
        [self presentViewController:controller animated:YES completion:NULL];
    }];
}
ポイント2つ。
  1. 遷移する時にModalView1Controllerで実装してるmyDelegateにselfを設定しておく。
  2. delegateメソッドが呼ばれたら表示中のModalView1Controllerを閉じ、閉じる処理が完了したらModalView2Controllerを起動させる。

完成

実装は終わりましたので確認してみてください。

2013年1月14日月曜日

iOS6以上でのstoryboard上のローカライズ対応


すっかりブログ書くことを忘れてたので初めての会社ブログへの投稿になります。鯱ブログだし休日に会社ブログ書くとらしい鯱れるね。

iOS6からstoryboard上のローカライズ対応が楽になりました!楽になった方法を書こうと思いますが、楽になったのは設定時であって前準備は非常にメンドウです。くじけぬ心を装備して臨みましょう。

Step1. プロジェクト作成

まずはXcodeでプロジェクトを作成してください。今回はiPhone/iPadのstoryboardを追加した状態で解説していきます。


Step2. Localizable.strings作成

Finderから「プロジェクト/en.lproj」ディレクトリに "Localizable.strings" ファイルを作成します。

今回の初期設定時に巻き込んで作ってしまうと楽なので含めている為、今回このファイルは使いません。不要ならこのStepは飛ばしてください。
コード上で以下のように記述する事で利用します。
NSLocalizedString(@"kye", @"comment");

Step3. Base.lproj作成

Xcodeで「Project > info> Localizations > + > Other > Base(Base)」を選択。
ローカライズ対象のファイルを選べというアナウンスがあるので、全てチェックが付いた状態で「Finish」を押します。


結果、Baseとenはこんな感じになります。

Step4. *.storyboard用の*.stringsファイル作成

ターミナルから「プロジェクト/Base.lproj」で以下のibtoolコマンドを実行します。それぞれstoryboardに対応したstringファイルなので、そのディレクトリにあるstoryboard名が異なれば内容変更して実施ください。
ibtool --export-strings-file MainStoryboard_iPhone.strings MainStoryboard_iPhone.storyboard 
ibtool --export-strings-file MainStoryboard_iPad.strings MainStoryboard_iPad.storyboard
こんな感じに*.storyboardに対し、*.stringファイルが増えていればOK。

Step5. *.stringsファイル移動

Base.lprojに作成した.*stringsファイルを、en.lprojディレクトリにFinder(実際のファイルをって事)で移動させます。
これでBase.lprojディレクトリに2ファイル、en.lprojディレクトリに4ファイルです。


Step6. Xcodeに今まで作成したファイルを追加

追加したLocalizable.stringsとstoryboardの*.stringファイルをXcode上に追加します。
Xcodeから「メニュー > Add Files to "プロジェクト名"」から"Base.lproj"と"en.lproj"を選択します。
Xcode上で*.storyboardとInfoPlist.stringsが重複して邪魔なので消します。

Step7. 対応言語の追加

英語以外の言語を追加していきます。今回は"Japanese(jp)"を選びます。

まローカライズ対象のファイルを選べというアナウンスがあるので、 *.storyboard以外の全てにチェックを付けた状態で「Finish」を押します。
"MainStoryboard_iPad.storyboard" や "MainStoryboard_iPhone.storyboard" ファイルにチェックを付けないのがポイントです。

これで、LanguageにJapaneseが増えます。

Xcode上で見ると "InfoPlist.strings", "Localizable.strings", "MainStoryboard_iPad.strings", "MainStoryboard_iPhone.strings" に▶印がついて、▼するとEnglishとJapaneseの2言語が設定出来る状態になりました。

これで前準備は終わりになります。慣れれば簡単なのかな?いあそんなことは...


Step8. storyboard上でUI作成

iPhoneのstoryboardを対応してみましょう。"MainStoryboard_iPhone.storyboard" を開いて適当にUI作成してください。
今回は以下のように作成してみました。

Step9. storyboardに表示するテキストをローカライズ対応

"MainStoryboard_iPhone.strings"ファイルの英語or日本語を開いて以下のようにkey-valueを設定していきます。
"key" = "value";
ここで重要なのはkeyの方です。keyは"MainStoryboard_iPhone.storyboard" を開いて、文字を表示させる対象の部品を選択し、storyboardの右Viewの左から3つ目にあるタブにある「Object ID」と値を設定したいプロパティ名になります。
もうひとつ大事なポイントとして、対象のプロパティには何かしらの文字を設定しておいてください。未設定だとkeyに対応したvalueが設定されません。


例えばUILabelの場合、私が作成したstoryboard上ではObject-IDが "udb-le-F0F" でした。これに表示させたい対象のプロパティ名 "title" を組み合わせた "udb-le-F0F.title" がkeyとなります。"MainStoryboard_iPhone.strings" 上には以下のように書きます。
"udb-le-F0F.title" = "Localize"; // 英語ファイル
"udb-le-F0F.title" = "ローカライズ"; // 日本語ファイル
なお、今回iPhoneだけstringファイルを弄りましたが、このままではiPad側のstringファイルに何も書かれていない為、エラーになってしまいます。たとえ未使用でも*.stringファイルには何か書いておく必要があるのでご注意を。
storyboard上に文字を挿入したい時はこのStepを毎回行う必要があります。


Step10. ローカライズされた事を確認

これでローカライズ対応は終わりました。言語表示が"英語"と"日本語"で検証してみてください。
切替方法は「Settingsアプリ > General > International > Language」となります。

もしうまく表示されない時はcleanするなり、アプリを一度削除する必要があります。


備考. 適当に試してみた

 

MainStoryboard_iPhone.strings(en.lproj)

/* UITabBarItemObject-IDUINavigationBar自体ではなく、Title部分のUIBarButtonItemな事に注意 */
"QxD-1d-LR4.title" = "Search";"hjG-GX-5Zj.title" = "Fav"; 
/* NavigationBar上のタイトル。Object-IDUINavigationBar自体ではなく、Title部分のUIBarButtonItemな事に注意 */
"udb-le-F0F.title" = "Localize"; 
/* UIBarButtonItem */
"HHM-r4-1XD.title" = "Push";
/* UILabel */
"3b5-Va-UMR.text" = "subakolab Inc."; 
/* UITextField */
"beM-F3-IQy.placeholder" = "hogehoge";"VKy-Ty-8Nf.text" = "input"; 
/* UIButton */
"Lrt-NR-GvK.normalTitle" = "tararara"; 

MainStoryboard_iPhone.strings(ja.lproj)

/* UITabBarItem */
"QxD-1d-LR4.title" = "検索";"hjG-GX-5Zj.title" = "お気に入り";
/* NavigationBar上のタイトル */
"udb-le-F0F.title" = "ローカライズ"; 
/* UIBarButtonItem */
"HHM-r4-1XD.title" = "押して"; 
/* UILabel */
"3b5-Va-UMR.text" = "株式会社スバコラボ"; 
/* UITextField */
"beM-F3-IQy.placeholder" = "ほげほげ";"VKy-Ty-8Nf.text" = "入力"; 
/* UIButton */
"Lrt-NR-GvK.normalTitle" = "たららら";


余談

 ブログに書くのが途中で面倒くさくなって投げそうになったのをグッと我慢して書いたのでゼヒゼヒお試しください。
何が面倒臭かったかと言うと今現在Bloggerのデザイン変更権限がアカウントに付与されてないせいで、ソースコードを綺麗にハイライトしてくれるjsを組み込めなかったせいで自分でハイライトさせた事ですね。そのままだと見難いし、でも面倒くさいしの間でたゆたってました。

2012年12月18日火曜日

UIViewをtransformで回転させるときに気をつけること

例として、こんなラベルが定義されてるとして話を進めます。

UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(006030)];
label.text = @"ABCDE";
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor blueColor];


1.回転を行うとframeが変更される
次のようなコードで90度回転させるとします。
 
label.transform = CGAffineTransformMakeRotation(M_PI_2);

そうするとframeのCGRectは、

origine: x=15, y=-15
size: width=30, height=60

と変更されてしまいます。
また、対象が斜め向きになる角度(45度とか)で回転させると、回転後の対象がちょうど収まるCGRectに変更されます。

当然ですが、この時点で次のように元々と同じframeをセットしても回転状態はキープされているのでおかしな表示になっってしまいます。

label.frame = CGRectMake(00, 6030);


2.回転後にビューのサイズを変更する場合は、boundsを再設定するか一度回転をリセットしてframeを再設定する
これは必ずしもと言うわけではないのですが、そうしておくと分かりやすくなることが多いと思います。
というのも、1の通り回転後はframeが変更されているので、frameを再設定して正確にサイズを変えようと思うと、に再設定するCGRectのサイズを計算する必要が出てきます。
(多分三角関数的なアレになると思うのですがそこまで調べてはいません。)

label.transform = CGAffineTransformMakeRotation(M_PI_2/2);
label.bounds = CGRectMake(009030);

あるいは

label.transform = CGAffineTransformMakeRotation(M_PI_2/2);
label.transform = CGAffineTransformMakeRotation(0);
label.frame = CGRectMake(009030);
label.transform = CGAffineTransformMakeRotation(M_PI_2/2);

boundsの場合は中心位置がリサイズ前のままになり、リセット+frameの場合はリサイズ後の中心位置を基準に回転することになるので、その点は注意が必要です。


3.基準となるCGAffineTransformを指定しないと無回転状態を基準に回転する
連続して回転させる場合、以下のように現在のCGAffineTransformを基準として指定してやる必要があります。

label.transform = CGAffineTransformRotate(label.transform, M_PI_2)
label.transform = CGAffineTransformRotate(label.transform, M_PI_2)

以下のようにしてもずっと90度のままです。

label.transform = CGAffineTransformMakeRotation(M_PI_2);
label.transform = CGAffineTransformMakeRotation(M_PI_2);

transformに保持しているCGAffineTransformを設定し直すので当然と言えば当然ですね。


2012年12月12日水曜日

UIWindowは回転しない

iOSアプリ開発、Mac使用歴共に4ヶ月と少しのの社員4です。
わからないことだらけのiOS SDKやXCodeと日々格闘しております。
そんな中で気づいたことを書き留めていこうと思います。

さて表題の件ですが、アプリの画面回転を有効にしている場合、rootViewControllerのviewは自動的に回転してくれるのですが、windowは回転してくれません。
ですので、windowになんらかのviewを直接addsubviewしている場合は、viewを個別に回転させたり、回転に応じて座標を変換する必要があります。


検証環境はXCode4.5とiOS4.3、5.1、6.0です。(いずれもシュミレータ)



検証用コード
-(void)viewDidAppear:(BOOL)animated
{
    self.view.backgroundColor = [UIColor clearColor];
    
    UIView *markerV = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
    markerV.backgroundColor = [UIColor blueColor];
    [self.view addSubview:markerV];
    
    UIView *markerW = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
    markerW.backgroundColor = [UIColor redColor];
    [self.view.window addSubview:markerW];
}