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

2014年9月10日水曜日

【Objective-C】Game Centerに対応したアプリの作り方(実装編)


iTunes Connect側の設定ができていない場合は下記をはじめにお読みください。
【Objective-C】Game Centerに対応したアプリの作り方(準備編)


簡単に手順を説明します。(Appleの公式のガイドも参照してください)

1.Game Centerへのログイン処理
2.スコアの送信
3.リーダーボードの参照

大きくわけて、以上の3つになります。

1に関してはアプリ起動時の最初の処理で実装します。
/**
 * GameCenterにログインしているか確認処理
 * ログインしていなければログイン画面を表示
 */
- (void)authenticateLocalPlayer
{
    GKLocalPlayer* player = [GKLocalPlayer localPlayer];
    player.authenticateHandler = ^(UIViewController* ui, NSError* error )
    {
        if( nil != ui )
        {
            [self presentViewController:ui animated:YES completion:nil];
        }
        
    };

}

これで無事画面上部にGame Centerへのログインが表示されます。

2に関しては、ボードのスコアタイプごとに実装方法は変わってきます。
Elapsed Time To The Hundredth of a secondを例にして説明していきます。

00:00:00.00形式のことです。
スコアは時分秒の部分はすべて秒数に変換します。
_gameScore = [NSString stringWithFormat:@"%d.%d" ,((hour * 3600) + (minute * 60) + second) ,miliSec].doubleValue * 100;

そして、ミリ秒の部分は小数点として結合します。
例えば 00:05:10:22 ▶︎ 310.22とします。
これを100倍した、31022をスコアに送信すると仕様になっているようです。
スコアは、下記を実装することにより送信可能です。

// GameCenter スコア送信
        if ([GKLocalPlayer localPlayer].isAuthenticated) {
            GKScore* score = [[GKScore alloc] initWithLeaderboardIdentifier:@"Stage1"];
            score.value = _gameScore;
            [GKScore reportScores:@[score] withCompletionHandler:^(NSError *error) {
                if (error) {
                    // エラーの場合
                }
            }];
        }


3に関しては、下記を実装して実施します。
/**
 * リーダーボードで完了タップ時の処理
 * 前の画面に戻る
 */
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController
{
    [self dismissViewControllerAnimated:YES completion:nil];
}


- (IBAction)btnRanking:(id)sender {
    GKGameCenterViewController *gcView = [GKGameCenterViewController new];
    if (gcView != nil)
    {
        gcView.gameCenterDelegate = self;
        gcView.viewState = GKGameCenterViewControllerStateLeaderboards;
        [self presentViewController:gcView animated:YES completion:nil];
    }
}

ボタンを用意して、ボタンが押下されときのイベントに紐付けします。これでランキングを見ることができます。
ちなみに、実機テストでは、サンドボックスモードにしないと、Game Centerにログインができないので要注意です。iPhoneの設定から変更できます。

すでにアプリが出来上がっている場合は、準備編から実装編あわせても、30分もかからずに実装することができると思います。

【Objective-C】Game Centerに対応したアプリの作り方(準備編)

■ iTunes Connectの設定

Appの管理からゲームセンターの設定に行きます。
ここではアプリごとにゲームセンターのスコアを送信するためのボードを作成していきます。複数のステージがある場合には、複数のボードを作成して、ステージ毎のスコアを競うことができます。

1.ゲームセンターの有効化
Game Center をEnabledにすること。
次にLeader Boardの追加をします。










2.Leader Boardの追加








スコアの種類、タイプ、並べ替えの順序など設定していきます。
例えば、シューティングゲームなどの点数を競う場合は、ベストスコア、スコアの降順の設定をし、カートのゲームなどでタイムを競う場合は、スコアの昇順での設定をするようです。ここで設定したボードのIDでアプリ側から参照をするので、覚えておいてください。

3,Leader Boardのローカリゼーション







Leader Boardの名前、得点のフォーマット、得点の単位(exp , pt)など好きに設定をできます。各国ごとにローカライズしてきましょう。
また、Game Centerのイメージアイコンが必要になりますので、用意しておく必要があります。サイズは512 * 512の大きさのものとなります。

ここまでで、無事にボードの作成はできました。しかし、これではまだGame Centerは有効にはなりません。次にAppの管理で現在のアプリのVersionを選択して、Game Centerを有効化する必要があります。

4.アプリのVersion





ここで+を押下すると先ほど追加して先ほど追加したボードをアプリに登録します。
Game CenterをEnabledにすることも忘れずに・・・。
これで、iTunes Connect側の設定は完了です。

次はアプリ側の実装方法について説明していきます。

【Objective-C】Game Centerに対応したアプリの作り方(準備編)



2014年8月31日日曜日

【Objective-C】iPhoneのアプリ名をアプリ名を多言語化(ローカライズ)する方法


1 PROJECTからInfoを選択し、 Localizationsの+を追加して、Japaneseを追加する。








2 Supporting Filesフォルダ内のInfoPlist.stringsを展開して、
  Japaneseが追加されていることを確認し、各ファイル内に以下を設定する。


 
 



■ Japanese
CFBundleDisplayName = "あああ";

■ English
CFBundleDisplayName = "AAA";

このような設定をすることにより、アプリ名が言語によって変更できます。

2014年8月30日土曜日

【Objective-C】カウントアップするタイマーの作り方(ミリ秒まで)

タイマー開始前に時間表示用のラベルの初期化、開始時刻の取得をします。
その後、タイマーのインターバルにはSelectorで指定されているメソッドの呼び出し頻度を設定し、タイマーをリピートさせて開始します。
これにより、onTimerメソッドが0.01秒単位で呼び出しされる。
onTimerにて、開始時刻と現在時刻を比較する。比較結果から分・秒・ミリ秒を求めて、時間表示用のラベルに代入する。
ちなみに、タイマーを停止する場合は、invalidateメソッドを使用します。


■ ヘッダーファイル
NSTimer        * _timer;
NSDate         * _stTime;
@property (weak, nonatomic) IBOutlet UILabel *lblTime;

▪ ソースファイル
- (void)viewDidLoad
{
    self.lblTime.text = @"00:00.000";
    _stTime = [NSDate date];
    _timer = [NSTimer scheduledTimerWithTimeInterval:(0.01)
                                              target:self selector:@selector(onTimer:)
                                            userInfo:nil repeats:YES];
    [_timer fire];
}

- (void)onTimer:(NSTimer*)timer {
    NSTimeInterval dateDiff = [[NSDate date] timeIntervalSinceDate:_stTime];
    //int hour   = dateDiff / (60 * 60);
    int minute = fmod((dateDiff / 60) ,60);
    int second = fmod(dateDiff ,60);
    int miliSec = (dateDiff - floor(dateDiff)) * 1000;
    self.lblTime.text = [NSString stringWithFormat:@"%02d:%02d.%03d",minute,second,miliSec];
}


【Objective-C】文字列から配列を生成する方法

文字列から配列を生成するにはcomponentsSeparatedByStringを使用する。

NSString *data = @"a,b,c"
NSArray *arr = [data componentsSeparatedByString:@","];

data[0] → a
data[1] → b
data[2] → c

2014年8月29日金曜日

【Objective-C】LABEL等のオブジェクトに枠線をつける方法

プロパティからは設定できないので、下記のように実装する必要があります。

#import <QuartzCore/QuartzCore.h>

// 枠線の色
[[self.lblSample1 layer] setBorderColor:[[UIColor whiteColor] CGColor]];
[[self.lblSample1 layer] setBorderWidth:1.0];

2014年5月31日土曜日

【Objective-C】iPhoneの書式設定に応じて日付表記を変える方法

日本の書式の場合
 2014年5月31日土曜日
アメリカの書式の場合
 Saturday, May 31, 2014

NSDateFormatterのsetDateStyle、setTimeStyleの指定を変える事によって、上記書式以外にも変換出来ます。

    NSDate          *date = [NSDate date];
    NSDateFormatter *df  = [[NSDateFormatter alloc]init];
    [df setLocale:[NSLocale currentLocale]];
    [df setDateStyle:NSDateFormatterFullStyle];
    [df setTimeStyle:NSDateFormatterNoStyle];

    self.labelDate.text = [df stringFromDate:date];


【Objective-C】TableCellに追加してオブジェクト種類を調べる方法

このソース例ではTableCellに追加したボタンをTableのEditモードかどうか判定して、表示したり、非表示したりする処理です。
Cellに乗っかっているオブジェクトをFor文でまわし、isMenberOfClassでUIButtonかどうか判定して処理を実装する。

- (void) cellEditMode:(BOOL) isEdit{
    NSArray * visibleCells = [self.tableView visibleCells];
    
    for (UITableViewCell *cell in visibleCells){
        for (UIControl *object in [cell.contentView subviews]) {
            if([object isMemberOfClass:[UIButton class]]){
                object.hidden = isEdit;
            }else{
                object.enabled = isEdit;
            }
        }
    }

}

【Objective-C】toolBarに動的にボタンを追加する方法

StoryBoard上でtoolBarを追加します。下記のメソッドを実行して動的にボタンを追加できます。self.toolbarItems = nilでtoolBarのアイテムをすべて削除しています。ボタン間に均等に間隔を空けるためFlexibleSpaceを設定します。




- (void) createToolBarItemEdit{
    NSString *btnStr;
    
    self.navigationController.toolbarHidden = NO;
    self.toolbarItems = nil;
    
    UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc]
                                     initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                     target:nil
                                     action:nil];
    
    //左のボタン
    if([self isLocaleJapanese]){btnStr = @"すべて選択";}else{btnStr = @"Mark All";}
    UIBarButtonItem * barButtonLeft = [[UIBarButtonItem alloc]
                                       initWithTitle:btnStr
                                       style:UIBarButtonItemStyleBordered
                                       target:self
                                       action:@selector(btnMarkAll:)
                                       ];

    //中のボタン
    UIBarButtonItem * barButtonCenter = [[UIBarButtonItem alloc]
                                         initWithBarButtonSystemItem:(UIBarButtonSystemItemAdd)
                                         target:self action:@selector(btnAdd:)
                                         ];
    
    //右のボタン
    if([self isLocaleJapanese]){btnStr = @"ゴミ箱";}else{btnStr = @"Trash";}
    UIBarButtonItem * barButtonRight = [[UIBarButtonItem alloc]
                                        initWithTitle:btnStr
                                        style:UIBarButtonItemStyleBordered
                                        target:self
                                        action:@selector(btnTrash:)
                                        ];
    
    self.toolbarItems = @[barButtonLeft ,flexibleItem ,barButtonCenter,flexibleItem ,barButtonRight];
    

}




【Objective-C】iPhoneに設定されている言語が日本語かどうか判定する方法


-(BOOL)isLocaleJa{
    //まず言語のリストを取得します。
    NSArray *languages = [NSLocale preferredLanguages];
    // 取得したリストの0番目に、現在選択されている言語の言語コード(日本語なら”ja”)が格納されるので、NSStringに格納します。
    NSString *languageID = [languages objectAtIndex:0];
    
    // 日本語の場合はYESを返す
    if ([languageID isEqualToString:@"ja"]) {
        return YES;
    }
    
    // 日本語の以外はNO
    return NO;

}

2014年5月10日土曜日

【Objective-C】UIActivityIndicatorViewを使用してインジケータを表示する方法

画面表示時に重たい処理をメインスレッドで実施すると、端末がフリーズしたように感じてしまいます。一般ユーザーは画面が表示された瞬間にスクロールやタップを開始するので、数秒間の処理でもフリーズしたと思われてしまいます。
これを回避するにはGCD(rand central dispatch)というマルチスレッドプログラミングを実装します。簡単にいうと、『メインスレッドには重たい処理は書かない、重たい処理は非同期の別スレッドに書く』ということです。今回はバックグラウンドでの重たい処理を実行中にインジケータを表示しています。

では、インジケータのサンプルプログラムを説明します。

まずはヘッダーファイルに、GCDで使用するキューと、インジケータを定義します。

■ヘッダーファイル
dispatch_queue_t _main_queue;
dispatch_queue_t _sub_queue;
UIActivityIndicatorView *_indicator;

Viewのロードイベントでインジケータを設定します。
スタート(開始)するにはstartAnimatingメソッドを使用します、ストップ(停止)するにはstopIndicatorメソッドを使用します。
インジケータに_indicator.hidesWhenStopped = YESを設定しているので、ストップ時に自動的に非表示になるようです。

サンプルプログラムの流れは下記のようになります。
メイン処理
 ・インジケータのスタート
  ▶︎画面にくるくるが表示される

 バックグラウンド処理
  ・通信、集計などの重たい処理
  ・インジケータのストップ(メインスレッドでやる)

ポイントはインジケータのスタート、ストップともにメインスレッドで実装する必要がああるということ。ストップはバックグラウンドの重たい処理が終わったら実施する必要があります。サンプルではperformSelectorOnMainThreadを使用してバックグラウンドからメインスレッドで実施するように書いています。

動作の流れとしてはインジケータがスタートし、バックグラウンドに処理を投げて、画面を表示する。その際に画面上にはくるくるとインジケータが表示されて見える。また、メインスレッドで処理は動いていないため、ユーザーは画面を動かす事もできます。この間バックグラウンドで、画面に表示するためのデータを作成し、作成完了後にバックグラウンド処理からインジケータのストップ処理をメインスレッドで実施するようにしています。

よくあるインジケータが表示されませんという話は、
メイン処理に
・インジケータのスタート
・通信、集計などの重たい処理
・インジケータのストップ
と書いているからです。
このような書き方では、画面にインジケータは表示されません。
上記3つの処理が終わった結果が表示されるだけです。また、メインスレッドでの処理中は画面操作が出来ません。よって、フリーズしているように感じとられてしまいます。


■ソースファイル
- (void)viewDidLoad
{
    [super viewDidLoad];

    // UIActivityIndicatorViewのインスタンス化
    CGRect rect = CGRectMake(0, 0, 100, 100);
    _indicator = [[UIActivityIndicatorView alloc]initWithFrame:rect];
 
    // 位置を指定
    _indicator.center = self.view.center;
 
    // アクティビティインジケータのスタイルをセット
    _indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
 
    _indicator.hidesWhenStopped = YES;
 
    // UIActivityIndicatorViewのインスタンスをビューに追加
    [self.view addSubview:_indicator];
}

// テーブルデータ作成
- (void) createTableData{
    // メインスレッド用で処理を実行するキューを定義するする
    _main_queue = dispatch_get_main_queue();
    // サブスレッドで実行するキューを定義する
    _sub_queue = dispatch_queue_create("tableLoad", 0);

    // くるくるを表示する
    [_indicator startAnimating];
 
    // サブキュー実行
    dispatch_async(_sub_queue, ^{
        //重たい処理を実装する

        //インジケータ消す
        [self performSelectorOnMainThread:@selector(stopIndicator) withObject:nil waitUntilDone:NO];
        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
     
        // メインキュー実行
        dispatch_async(_main_queue, ^ {


        });
    });  
}

【Objective-C】UIImageView上のイメージ画像(UIImageView)をダブルタップして拡大・縮小する方法

ジェスチャーを登録し、タップ時に呼ばれるイベントメソッドをセレクタに指定します。
ダブルタップの判定として、numberOfTapsRequired = 2とします。
メソッド側にてscrooViewのサイズを変更させます。

- (void)viewDidLoad
{
    [super viewDidLoad];
   
    UITapGestureRecognizer *doubleTap =
    [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(doubleTap:)];
    doubleTap.numberOfTapsRequired = 2;
    [self.view addGestureRecognizer:doubleTap];
}


- (void)doubleTap:(UITapGestureRecognizer *)recognizer {
    CGPoint location = [recognizer locationInView:[recognizer.view superview]];
   
    CGRect zoomRect;
    if (self.scrollView.zoomScale > 1.0) {
        zoomRect = self.scrollView.bounds;
    } else {
        zoomRect = [self zoomRectForScrollView:self.scrollView
                                        withScale:2.0
                                    withCenter:location];
    }
    [self.scrollView zoomToRect:zoomRect animated:YES];
}

【Objective-C】UIImageView上のイメージ画像(UIImageView)をピンチして拡大・縮小する方法

UIScrollViewの上にUIImageViewを追加する。
ヘッダーファイルにUIScrollViewのデリゲートを設定する。
ソースファイルでUIScrollViewの拡大率の設定して、デリゲートメソッドを定義する。これだけで、イメージ画像の拡大、縮小が可能です。

■ヘッダー
@interface ViewControllerPhoto : UIViewController<UIScrollViewDelegate>
{
}
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@end

■ソース
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.scrollView.minimumZoomScale = 1.0f;
    self.scrollView.maximumZoomScale = 3.0f;
    self.scrollView.delegate = self;

}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return self.imageView;
}

2014年4月19日土曜日

【Objective-C】UITableViewのEditMode(編集モード)時に行をすべて選択する方法

テーブルのセクションが1つの場合のサンプルプログラムです。テーブルの行を配列に取得して、各行に対してselectRowAtIndexPathでセクション(このサンプルでは0固定)と行番号を指定します。


■画面イメージ





//表示されている行のみチェックする場合
- (IBAction)btnMarkAll:(id)sender{
    NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
    for(NSIndexPath *indexPath in indexPaths){
        [self.tableView selectRowAtIndexPath:
         [NSIndexPath indexPathForRow:indexPath.row inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

すべてをチェックする場合はtableデータソースである配列を指定してまわせばできます。
//MarkAllボタン
- (IBAction)btnMarkAll:(id)sender{
    for (int i = 0; i < [_tableKey count]; i++) {
        [self.tableView selectRowAtIndexPath:
         [NSIndexPath indexPathForRow:i inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
    }

}





2014年3月22日土曜日

【Objective-C】Viewに追加されたUITextFiledのタグを指定して値を取得する方法

親画面に複数のテキストフィールドがあり、入力を子画面のポップアップでさせた場合に、どのテキストフィールドに入力値を反映させるかの判定に使用出来ます。このやり方を知る前はswitch case tagで分岐して、代入先を静的に設定していました。

□ 前提
テキストフィールドにtagを設定しておく。
テキストフィールドの編集時にlastTagに該当テキストフィールドのtagを設定しておく。

□ サンプルソース
子画面の入力後のdelegateメソッド(updateData)でViewにtag指定してUITextFieldを取得します


- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    lastTag = textField.tag;
}

- (void)updateData :(NSString *) dataValue{
    // viewからtagを検索して
    UITextField* textField = (UITextField*) [self.view viewWithTag:lastTag];
    textField.text = dataValue;

}


2014年3月21日金曜日

【Objective-C】日付(年月日)、時間(時分秒)を求める


- (void) test
{
    NSDate *date         = [NSDate date];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comps;
    
    // 年月日
    comps = [calendar components:(NSYearCalendarUnit
                                  | NSMonthCalendarUnit
                                  | NSDayCalendarUnit)
                        fromDate:date];
    NSInteger year  = [comps year];
    NSInteger month = [comps month];
    NSInteger day   = [comps day];
    
    // 時分秒
    comps = [calendar components:(NSHourCalendarUnit
                                  | NSMinuteCalendarUnit
                                  | NSSecondCalendarUnit)
                        fromDate:date];
    NSInteger hour   = [comps hour];
    NSInteger minute = [comps minute];
    NSInteger second = [comps second];
    
    NSString *logs;
    //%03d
    logs = [NSString stringWithFormat:@"%d%02d%02d%02d%02d%02d",year,month,day,hour,minute,second];
    NSLog(@"%@",logs);

}

【Objective-C】Viewを閉じるソースコード

iOs6以降のview(画面)の閉じ方。

- (IBAction)btnBarBack:(id)sender {
    //警告あり
    //[self dismissModalViewControllerAnimated:YES];
    
    //警告なし
    [self dismissViewControllerAnimated:YES completion:nil];

}


【Objective-C】Dictionaryからkeyとvalを求めて配列に設定する方法

サンプルソースの説明
self.trMasterData.dictMstTrBuiにはあらかじめdictionaryのkey,valが登録されているものとします。dictionaryのallKeysメソッドでkeyの一覧、allValuesメソッドでvalueの一覧をそれぞれ取得し、可変長の配列にコピーしています。その際に(NSMutableArray *)と頭につけてキャストしています。

/* 定義 */
@property (nonatomic) NSMutableArray *arrAllKeysTrHdAll;
@property (nonatomic) NSMutableArray *arrAllValsTrHdAll;

/* サンプルメソッド*/
- (void) arrDataCreate{
    //初期化
    self.arrAllKeysTrHdAll = [[NSMutableArray alloc] init];
    self.arrAllValsTrHdAll = [[NSMutableArray alloc] init];
    
    //key ,val配列生成
    NSArray *arrAllKeys   = [self.trMasterData.dictMstTrBui allKeys];
    NSArray *arrAllValues = [self.trMasterData.dictMstTrBui allValues];
    
    //キャストして登録
    self.arrAllKeysTrHdAll = (NSMutableArray *)[NSArray arrayWithArray:arrAllKeys];
    self.arrAllKeysTrHdAll = (NSMutableArray *)[NSArray arrayWithArray:arrAllValues];

}



2014年3月18日火曜日

【Objective-C】DictionaryのKey(キー)とValue(値)を調べる方法

設定されている値を確認するには、下記のようにid型で取得して参照します。

    for (id key in [trData.dictMstTrBui keyEnumerator]) {
        NSLog(@"Key:%@ Value:%@", key, [trData.dictMstTrBui valueForKey:key]);
    }

2014年3月17日月曜日

【Objective-C】キーボードをタップで閉じる方法

テキストフィールドをタップすると画面下部からキーボードが自動に出てきますが、入力後も閉じません。そのため下部にあるボタンが押せなくなるなど問題が発生します。
下記コードを実装すれば、画面タップでキーボードが閉じます。

- (void)viewDidLoad
{

    [super viewDidLoad];

    // 背景をキリックしたら、キーボードを隠す
    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard)];
     gestureRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:gestureRecognizer];
    
}

// キーボードを隠す処理
- (void)closeKeyboard {
    [self.view endEditing: YES];
}