Monday, October 7, 2013

ローカライズの方法とアプリの申請

これもまた参考にしたリンクのメモ。
ローカライズの方法。

こちらが大変参考になる。
アプリの名前を言語によって変える
Xcodeでアプリ名を多言語に対応させる方法(ローカライズ)
アプリの中の写真や文章を他言語対応する方法
iPhoneアプリ開発者が知っておきたい「アプリを多言語化(ローカライズ)」する方法

次は申請!!
これらのリンクを参考に進めていきました。
iPhoneアプリ申請やAppleの審査に関するメモ
【まとめ】iPhoneアプリ Xcode4での iTunesConnectへ申請する方法まとめ

またこちらのリンクもリリースする前の確認事項のリンクがあり非常にありがたかったです。
Mac初心者のiPhoneアプリ開発記9 アプリ申請までの道


僕はitunesconnectを使用して申請しました。
デベロッパープログラムに登録しているアカウントでログインして、手順に従って入力事項を入力すれば以外とすぐ終わりました。

紹介画像などを様々な大きさで用意するのに時間がかかりましたが、それ以外は特に詰まったこともなかったです。

チュートリアルの作り方

初めてアプリを使用するユーザーにチュートリアルを見せますよね。
そのチュートリアルの作成です。

参考にしたのはこちら→UIPageControlの使い方
以下のサンプルコードはこちらのサイトのほぼ丸パクリです。

サンプルのチュートリアルです。

//
//  ViewController.h
//  SampleApp
// いらないコメント省略

#import 

@interface ViewController : UIViewController 

@end

// ViewController.m
#import "ViewController.h"

@interface ViewController () {
    UIPageControl *pager;
    UIScrollView *scroll;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)viewDidAppear:(BOOL)animated {
    int page = 3;
    
    // scrollを作成
    scroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 100)];
    scroll.contentSize = CGSizeMake(self.view.frame.size.width * page, self.view.frame.size.height - 150);
    scroll.backgroundColor = [UIColor clearColor];
    
    // ページング指定
    scroll.pagingEnabled = YES;
    
    // スクロールバーを表示しない
    scroll.showsHorizontalScrollIndicator = NO;
    scroll.showsVerticalScrollIndicator = NO;
    // ステータスバータップで上に戻らない。
    scroll.scrollsToTop = NO;
    // delegate
    scroll.delegate = self;
    
    // scroll内で表示するViewを作る。
    for (int a = 0; a < page; a++) {
        UIView *view = [[UIView alloc]initWithFrame:CGRectMake(self.view.frame.size.width * a + 20, 20, self.view.frame.size.width - 40, self.view.frame.size.height - 170)];
        switch (a) {
            case 0:
                view.backgroundColor = [UIColor redColor];
                break;
            case 1:
                view.backgroundColor = [UIColor blueColor];
                break;
            case 2:
                view.backgroundColor = [UIColor greenColor];
                break;
            default:
                break;
        }
        [scroll addSubview:view];
    }
    
    
    // pagerを作る
    pager = [[UIPageControl alloc] initWithFrame:CGRectMake((self.view.frame.size.width / 2) - 20, self.view.frame.size.height - 40, 40, 20)];;
    pager.numberOfPages = page;
    pager.currentPage = 0;
    pager.pageIndicatorTintColor = [UIColor colorWithRed:0.84f green:0.85f blue:0.86f alpha:1.0f];
    pager.currentPageIndicatorTintColor = [UIColor blackColor];
    
    [pager addTarget:self action:@selector(changePageControl:) forControlEvents:UIControlEventValueChanged];
    
    [self.view addSubview:pager];
    [self.view addSubview:scroll];
}

// scrollしたときのdelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    // UIScrollViewのページ切替時イベント:UIPageControlの現在ページを切り替える処理
    pager.currentPage = scroll.contentOffset.x / self.view.frame.size.width;
}

// pagerのバリューに伴ってscrollも移動させる
- (void)changePageControl:(id)sender {
    
    // ページコントロールが変更された場合、それに合わせてページングスクロールビューを該当ページまでスクロールさせる
    CGRect Aframe = scroll.frame;
    Aframe.origin.x = self.view.frame.size.width * pager.currentPage;
    Aframe.origin.y = 0;
    // 可視領域まで移動
    [scroll scrollRectToVisible:Aframe animated:YES];
}


@end


次はこれを踏み台にして、Safariみたいな複数のページを自分で切り替えられるようなものを実装します。

アプリのアイコンを作成するのに参考にした画像など

まずはデフォルトアイコンやスプラッシュ画面のサイズ、名称を参考にさせていただいたリンク
iOSアイコンファイル早見表(2013/9)
すんばらしく見やすい。これ見て一発でわかった。
まじ感謝


Xcode5からはアイコンやスプラッシュ画面専用のImages.xcasesetsが出てきたからかなり管理しやすくなった。
アプリをリリースするの初めてだから、Xcode4でどうやって管理していたかは知らないけど。。。

アイコンやスプラッシュ画面などの画像はこちらのwebサービスを使いました。
簡単に文字や、背景色、文字色を指定した好きな大きさの画像が作れる大変優れたサービスです。
dummyimage.com

ここで無地の画像を作成して、Mac純正の画像にリサイズ、Skitchという無料のアプリで文字を入れたりしました。

今回作ったアプリはこんな感じのアプリです。
タイトルは「One Habit Log」。その名の通り一つの習慣しか記録することが出来ません。

これが最初アプリを起動した画面
右上のタイトルをクリックすると意気込みやタイトルをつけることが出来ます。
日付を指定すると下から、ボタンが出てきて記録することが出来ます。
記録した後の画面。

記録が目的なので今日の日付以降は記録することが出来ません。

次の記事はおそらくチュートリアルの作り方です。




Sunday, October 6, 2013

Magical Recordの使い方

やっとMagical Recordが使えるようになったのでメモしておく。
Personというエンティティ名をサンプルとして使用する。
こんな感じのデータ構造になっております。

Person
--name
--age

Insert

[MagicalRecord setupCoreDataStack];

Person *person = [Person MR_createEntity];
person.name = @"Sato Taro";
person.age = [NSNumber numberWithInt: 19];
これだけで新しいPersonを作成することが出来る。

Select

 
[MagicalRecord setupCoreDataStack];
NSArray *persons = [Person MR_findAllWithPredicate:[NSPredicate predicateWithFormat:@"(name == '%@')", @"Sato Taro"]];
これが単純なセレクト
ANDでつなぐ場合
[MagicalRecord setupCoreDataStack];
Person *person = [Person MR_findFirstWithPredicate:[NSPredicate predicateWithFormat:@"(name == 'Sato Taro') AND (age == 19)"]];
SORTしたいとき
[MagicalRecord setupCoreDataStack];
NSArray *persons = [Persn MR_findAllSortedBy:@"age" ascending:YES];
ほかにもっと複雑なセレクトを書けたいときは順次加えていく。

Update

[MagicalRecord setupCoreDataStack];
Person *person = [Person MR_findFirstWithPredicate: [NSPredicatepredicateWithFormat:@"name = 'Sato Taro'"]];
person.name = @"Sato Kogoro";
これだけ!

Delete

[MagicalRecord setupCoreDataStack];
Person *person = [Person MR_findFirstWithPredicate: [NSPredicatepredicateWithFormat:@"name = 'Sato Taro'"]];
[person MR_deleteEntity];

今のところこんな感じです。新しいことがわかったら随時加えていきます。

UIAlertViewにテキストのinputをさせる

参考→【iOS5】UIAlertViewにsetAlertViewStyleでテキストフィールドを追加する!!

ここを参考に僕も実装しました
- (void) settingButtonTapped {
    UIAlertView *setTitle = [[UIAlertView alloc] initWithTitle:@"Set Title"
                                                       message:nil
                                                      delegate:self
                                             cancelButtonTitle:@"Cancel"
                                             otherButtonTitles:@"Save", nil];
    [setTitle setAlertViewStyle:UIAlertViewStylePlainTextInput];
    [[setTitle textFieldAtIndex:0] setText:habit.title];
    [setTitle show];
}

// Setボタンを有効にするかを決める
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView {
    NSString *inputText = [[alertView textFieldAtIndex:0] text];
    
    if( [inputText length] >= 1 ) {
        return YES;
    } else {
        return NO;
    }
}

// アラートのsetTitleのsaveボタンが押された
-(void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    NSString *input = [[alertView textFieldAtIndex:0] text];

    if (buttonIndex == 1) {
        NSLoG(@"%@", input);
    }
}

Saturday, October 5, 2013

UIButtonをプログラムから作成する

このようなフラットデザインのボタンを作れるライブラリを使いながらボタンを作成したのでめもめも
QBFlatDesignについてはこちらのgithubプロジェクトを見ていただければわかるので、ここでは触れません。

では、ボタンをプログラムから作る方法と、クリックイベントの取得の方法をばここに。
    QBFlatButton *bottomButton = [[QBFlatButton alloc]initWithFrame: CGRectMake(20, frame.size.height - 80, frame.size.width - 40, 60)];
    // デフォルトのボタンを作るときは以下のコード
     UIButton *bottomButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // この場合あとでフレームを指定しないと行けない
    // font
    bottomButton.titleLabel.font = [UIFont boldSystemFontOfSize: 20];
    [bottomButton setTitle:@"Mark" forState:UIControlStateNormal];
    [bottomButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    // color
    bottomButton.faceColor = [UIColor colorWithRed:0.23 green:0.83 blue:.51 alpha:1];
    bottomButton.sideColor = [UIColor colorWithRed:.16 green:.76 blue:.44 alpha:1];
    // event
    [bottomButton addTarget:self action:@selector(bottomButtonTapped) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:bottomButton];

Friday, October 4, 2013

Xcodeでアニメーションさせる

何かをアニメーションさせながら非表示にしたいということはよくあると思う。
そんなときに使えるのがこのメソッド
- (void)viewDidLoad
{
    [super viewDidLoad];

     CGRect frame = self.view.bounds;

    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, frame.size.height - 100, frame.size.width, 100)];
    label.backgroundColor = [UIColor colorWithWhite:1 alpha:0.8];
    [self.view addSubview:label];

    [UIView animateWithDuration:0.5 animations:^{
        label.frame = CGRectMake(0, frame.size.height - 100, frame.size.width, 100);
    }];
}
このコードを動かすと、画面が表示されてから0.5秒掛けながら、画面の下から100px分表示されていた透明なバーが下に下がっていく。

おためしあれ〜〜

UIScrollViewでどれくらいはやく動いているかを取得する

UIScrollVIewでどれだけ動いたかを知りたくて、その方法を探していた。
UIScrollViewに限らず、UITableViewでも使える。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
{
    CGPoint velocity = [[scrollView panGestureRecognizer] velocityInView:self];
    if (abs(velocity.y) >= 800) {
        // do something
    }
}
これでvelocityの速度を違うメソッドに渡せば、Google+のiPhoneアプリのように、スクロールに合わせて表示、非表示の切り替えを行うことが出来る。

カレンダーライブラリ~MNCalendarView~

カレンダーアプリを作ろうと思い立ち、TapkuLibraryを使用できるようになったのはいいがそれでは僕がイメージしていたものができたいとわかったため、違うライブラリを探していた。

試していったのを順次使い方を含めて紹介していく。

MNCalendarView

非常に簡単に使用でき、なおデザインも最高にいい。

<手順>
こちらのGitHubプロジェクトから自分のパソコンへファイルを移動させる。形式はzipでも、gitでもなんでもいい。
そして、プロジェクトにMNCalendarViewをAdd Fileするだけ。とても簡単だ。以下のコードで画像のようなカレンダーが表示される。
// viewController.h
#import 
#import "MNCalendarView.h"

@interface ViewController : UIViewController

@end

// viewController.m
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
/*
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd"];
    NSString *dateString = @"2013-09-08";
    NSDate *date = [formatter dateFromString:dateString];
    これで始めの位置を指定しようとしたがかなわなかった。
*/
    MNCalendarView *calendar = [[MNCalendarView alloc]initWithFrame:self.view.bounds];
    calendar.selectedDate = date;
    [self.view addSubview:calendar];
}

- (void)didReceiveMemoryWarning {
    // 省略
}

@end

これでこのように表示される

デザインもシンプルでいいのだが、日付をタップされたときのイベントの取得がデフォルトでなく、また、カレンダーを表示させる位置も終わらせる位置もデフォルトでなかったので、ボツに

そこでTimesSquareを採用したのだが、これも長くなりそうなのでまた今度のエントリーにまとめます

TapkuLibraryのカレンダーで日付のタップイベントを取得する!

前回の記事で無事カレンダーを表示させるところまでいけたので、今回はカレンダーの日付をタップされたときのイベント取得を実装します。
前回の記事→TapkuLibraryのedgesForExtendedLayoutで悩んでいるすべての方へ


// viewController.h
// ここは前回の記事と変わらない。delegateが増えていることに注目
#import 
#import "TapkuLibrary/TapkuLibrary.h"

@interface ViewController : UIViewController 

@end

// viewController.m
#import "ViewController.h"

@interface ViewController () {
    TKCalendarMonthView *calendar;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    calendar = [[TKCalendarMonthView alloc]init];
    calendar.delegate = self;
    // calendar.dataSource = self;  * タップイベントを取得するだけだったらこれは必要ありません。
    [self.view addSubview:calendar];
}

- (void)didReceiveMemoryWarning {
// 省略
}

// カレンダーがタップされたイベントを取得
- (void)calendarMonthView:(TKCalendarMonthView *)monthView didSelectDate:(NSDate *)date {
    NSLog(@"tapped!!");
}

@end


TapkuLibraryのedgesForExtendedLayoutで悩んでいるすべての方へ

TapkuLibrary。。。すばらしいライブラリですよね。
デフォルトぽいカレンダーが数行で書けてしまいます。(僕はまだ表示させるところまでいっていない)

そんなTapkuLibraryですが、最近のiOS 7へのアップデートの影響でビルドが通らないことがあります。
その解決策です。

問題その1: "Property edgesForExtendedLayout not found on object"

ご心配には及びません。このエラーはすぐに解決できます。


まずこのエラーの原因ですが、iOS 7では存在するこのプロパティがiOS 6では存在しないことにより起きております。
証拠資料→UIViewController Class Reference


なので、「edgesForExtendedLayout」と書かれている行はすべてコメントアウトしてもかまいません。
本当はOSが7以上だったらで実行させたいところですが、xcodeをアップデートしないとこの行ではエラーがでるようになっているため、コメントアウトしか方法はありません。
iOS7かどうかを判別するif文はこちらのリンクをどうぞ
Writing iOS7 code that compiles against iOS 6 Base SDK

問題その2: "vImageBoxConvolve_ARGB8888"

これが問題になることもあります。「ARGB_8888」で検索してコメントアウトさせましょう。


無事、ビルドが通ればカレンダー表示!

問題なくビルドが通るようになったらいよいよviewにカレンダーを表示させます。


// viewController.h
#import 
#import "TapkuLibrary/TapkuLibrary.h"

@interface ViewController : UIViewController 

@end

// viewController.m
#import "ViewController.h"

@interface ViewController () {
    TKCalendarMonthView *calendar;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    calendar = [[TKCalendarMonthView alloc]init];
    [self.view addSubview:calendar];
}

- (void)didReceiveMemoryWarning {
//省略
}

@end


これだけでなんとすばらしいカレンダーが表示されてしまいます!
このように!

おためしあれ〜〜

xcode4で.xcdatamodeldファイルを作成

いつもhファイルとmファイルを加えるように「File -> New -> File」と選択していく。
そうするとこのようなダイアログウィンドーがでてくるから、
上の画像の通り、OS XのCore Dataを選択し、
上の画像の通りを加える。

そのあとに作成するxcdatamodeldのファイル名を決めなくてはならないが、最初はデファルとのModel.xcdatamodeldで問題ない。