月別アーカイブ: 2015年7月

Objective-Cでアチーブメント

iPhoneアプリに達成記録、Achievement(アチーブメント)を実装しようとしたが意外と情報がなかったので備忘録。

コチラiTunes Connect: Game Center の Achievement を設定する | siro:chroを参考に、itunes connectでAchievementを作ってから、

Game Centerプログラミングガイド – Apple Developer
詳解iOS5プログラミング – 沼田哲史 – Google ブックス
上記ページを参考に下記のようなコードを書いてみた。

- (void)sendAchievement{
    
    if (totalCount >= 100) {
        GKAchievement *achievement = [[GKAchievement alloc]initWithIdentifier:@"tamago100"];
        achievement.percentComplete = 100;//達成率
        achievement.showsCompletionBanner = YES;//達成した時に画面にバナー表示するか。

        [achievement reportAchievementWithCompletionHandler:^(NSError *error) {
            if (error) {
                NSLog(@"アチーブ100エラー"); //エラー表示
            } else {
                NSLog(@"アチーブ100成功");//達成項目のアップロードに成功
            }
        }];
    }
 }

すると、8行目で黄色三角がでて、
‘reportAchievementWithCompletionHandler:’ is deprecated: first deprecated in ios7.0 – Use +reportAchivements:withCompletionHandler:
と、ios7以降では推奨されない的なことを言われた。

よくわからないが、色々と調べるとこちらのサイトに行き着いた。
[self Achievements:achievement];

そしてコードを書きなおしてみた。

- (void)sendAchievement{
    
    if (totalCount >= 100) {
        GKAchievement *achievement = [[GKAchievement alloc]initWithIdentifier:@"tamago100"];
        achievement.percentComplete = 100;//達成率
        achievement.showsCompletionBanner = YES;//達成した時に画面にバナー表示するか。

        [self Achievements:achievement];
    }
}

-(void)Achievements:(GKAchievement*)achievement {
    
    NSArray *achievements = [NSArray arrayWithObjects:achievement, nil];
    [GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) {
        if (error != nil) {
            NSLog(@"Error in reporting achievements: %@", error);
        } else {
            NSLog(@"アチーブ成功");//達成項目のアップロードに成功
        }
    }];
}

これでエラーは消えた。

sendAchievementメソッドの中でif文を増やしていけば色々アチーブメントを追加できるとおもう。
しかし、点数の低いアチーブメントが毎回送られてしまう気がするが大丈夫なのかな?(^_^;)

ボタンを押した時に画像が変わるようにする。

xcodeには元々デフォルトのボタンが有り、色をつけたり、ある程度形を変えたり、画像を設定することが出来る。

しかし、ゲーム風やアナログ風のボタンを表示したい時もある。

ひょっとしたらxcodeの基本設定でなんとかなるものなのかもしれないけれど、よく判らんので自分なりにやってみた。

まずは、普通状態と押した時の状態のボタンの画像を用意する。
buttonRed普通
buttonRed2おした時

これらをナビゲータエリアにドラッグ・アンド・ドロップで入れる。
スクリーンショット 2015-07-21 12.31.57
アラートが出るのでCopy items if neededのチェックを確認してフィニッシュ。

右下のMedia Libraryに表示されるようになります。
スクリーンショット 2015-07-21 12.34.36

まず、ストーリーボードで普通状態のボタンを表示させるが、何もない状態でいきなり画像を置くと画面いっぱい最大サイズで表示されてしまうので、先にimage Viewを配置します。

さらにそのimage viewも何もない状態のストーリーボードに入れると、全画面のimage Viewになってしまうので先にラベル等を一つ置いておくと良い。
スクリーンショット 2015-07-21 11.26.36

スクリーンショット 2015-07-21 11.26.25

配置するとこんな感じ。
スクリーンショット 2015-07-21 11.26.54

UIImageViewは右のサイズインスペクタで希望のサイズにしておき、そこに右下のメディアライブラリーから普通状態の画像を入れるとイメージビューのサイズに合わせてボタンが表示される。
スクリーンショット 2015-07-21 11.27.35

ボタンの画像に重なるようにUIButtonを配置してサイズを調整します。
スクリーンショット 2015-07-21 11.29.05

スクリーンショット 2015-07-21 11.29.39

ボタンの画像はアウトレット接続、UIButtonは、「touch Down」、「touch Up Inside」、「touch Up Outside」の三種類でUIButton接続します。
スクリーンショット 2015-07-21 11.33.19

これはボタンを押した瞬間に押した状態の画像に変えて、ボタンから離した瞬間に元の状態の画像に戻すためです。
またこれだけでは、押した状態でスライドさせると押した状態のまま画像が変わらずに残ってしまうことを防ぐため、touch Up Outsideも設定します。

完成のコードがコチラです。

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *redButtonMitame;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

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

#pragma mark - IBAction
//ボタンに触れた時の動作
- (IBAction)redButtonOsu:(UIButton *)sender {
    [self redButtonOsita];
}

//ボタンを離した時の動作
- (IBAction)redButtonHanasu:(UIButton *)sender {
    [self redButtonNormal];
}

//ボタンを押して横にずらした時の動作
- (IBAction)redButtonZurasu:(UIButton *)sender {
    [self redButtonNormal];
}


#pragma mark - 画像の差し替え
//ボタンの画像をノーマル状態に差し替える。
- (void)redButtonNormal{
    self.redButtonMitame.image = [UIImage imageNamed:@"buttonRed.png"];
}

//ボタンの画像を押した状態に差し替える。
- (void)redButtonOsita{
    self.redButtonMitame.image = [UIImage imageNamed:@"buttonRed2.png"];
}

@end

これで、押した瞬間に画像が変わって離すと元に戻るボタンが出来るはずです。

もっと簡単な方法あるで、という方居られましたら教えて下さい。(−人−)

スクリーンショット 2015-07-21 12.59.09

追記7/22
よくよく考えて見ればボタンと画像を切り離す必要はなくボタンのアウトレット接続で画像を変えればよかったんだなと気付いた。
ま、初心者ゆえの過ちかな。(^_^;)

複数のアラートビューで引っかかった。

UIAlertViewの表示 | iPhoneアプリ備忘録でアラートビューについて書いた。

この時はひとつの画面でひとつのアラートだったのでよかったが、複数のアラートを使い分けるときに困った。
アラートを表示するのは良いが、それを受けるほうが、どのアラートから来たか知らせる方法がよくわからなかった。

参考にさせて頂いたサイト。
複数のUIAlertViewでdelegateを使い分ける – しゃの

とりあえず、tagを使うらしい。

#import "ViewController.h"
@interface ViewController ()//<UIAlertViewDelegate>
 
#pragma mark - アラートビュー
 
//アラートを作るときにタグを設定
 UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:@"タイトル"
                                                    message:@"メッセージ"
                                                   delegate:self
                                          cancelButtonTitle:@"キャンセル"
                                          otherButtonTitles:@"ボタン1",@"ボタン2", nil];
  alert1.tag = 1;//ここでタグを付ける
    [alert1 show];

〜〜
 UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:@"タイトル"
                                                    message:@"メッセージ"
                                                   delegate:self
                                          cancelButtonTitle:@"キャンセル"
                                          otherButtonTitles: nil];
  alert2.tag = 2;//ここでタグを付ける
    [alert2 show];
〜〜
 
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    //タグをチェック
    if (alertView.tag == 1)  {
        処理....
    }else if (alertView.tag == 2)  {
        処理....
}

アラートを作った時の変数のタグが、デリゲーションメソッドのタグに引き継がれるのでそれで判別するようです。

Objective-CでLine投稿

アプリからLineに投稿しましょう。

参考にさせて頂いたサイト。
Lineに投稿する | iPhoneアプリ練習帳

- (void)line
{
    NSString *textString = @"テキスト情報がはいります";
    textString = [textString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSString *LINEUrlString = [NSString stringWithFormat:@"line://msg/text/%@",textString];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:LINEUrlString]];
}

[self line]
で呼び出せばLineアプリに切り替わります。

Objective-CでFacebook投稿

アプリからフェイスブックに投稿しましょう。

Social Frameworkを使います。
ソーシャルフレームワークを追加してくださいね。

#import "ViewController.h"
#import <Social/Social.h>

@interface ViewController ()


- (void)facebook
{
    SLComposeViewController *fbVC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];

    [fbVC addURL:[NSURL URLWithString:@"http://apple.com/"]];//URLを入れる
    [self presentViewController:fbVC animated:YES completion:nil];//投稿ダイアログを表示する
}

[self facebook]
で呼び出せば投稿ダイアログが出ます。
連動で投稿できるのはURLだけのようですネ。

Objective-CでTwitter投稿

アプリからツイッターに投稿しましょう。

Social Frameworkを使います。
ソーシャルフレームワークを追加してくださいね。

#import "ViewController.h"
#import <Social/Social.h>

@interface ViewController ()


- (void)twitter
{
    SLComposeViewController *twVC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];

    [twVC setInitialText:@"つぶやくよ。"];//あらかじめテキスト入力
    [twVC addImage:[UIImage imageNamed:@"image.jpg"]];//画像を入れる
    [twVC addURL:[NSURL URLWithString:@"http://apple.com/"]];//URLを入れる
    [self presentViewController:twVC animated:YES completion:nil];//投稿ダイアログを表示する
}

[self twitter]
で呼び出せば投稿ダイアログが出ます。

UIButtonを一時的に無効にしたりする。

今回は自分の素人具合、初心者であることを痛感しました。(;´∀`)

前回、UISegmentedControlを使ってゲームのLevel設定をしたのですが、
ゲーム中もUISegmentedControlがアクティブのままで途中で切り替えれたり?訳わからんことになって困ってしまった。

UISegmentedControlを一時的に消したり、止めたり出来れば良いのですがやり方がわかりません。
IBActionで接続したボタン等をプログラムでいじるにはどうすればよいのか…。

散々悩んだ挙句、同じくiPhoneアプリを作っている友人に聞いた所、
「ボタンのenabledをNOとかにしてもいいし」とのこと。

enabledで検索、、、、、

、、、、、、

もしかして、UIButtonのたぐいもoutLet接続してよいのか?

そーです。
基本的に書籍かネットで調べて独学でやってたもんで、
ビュー関係はoutlet接続、
ボタン関係はaction接続と完全に思い込んでました。

こころのどこかで、なんで毎度接続方式を選択せにゃならんのだろう〜?とは思ってたんですけどね。

で、あらためて、ストーリーボードのUISegmentedControlから右クリックでViewControllerにひっぱってoutlet接続!!

ゲームをスタートしたタイミングのメソッドで

_levelChangeMitame.enabled = NO;//セグメンテッドコントロールをオフにする

ゲーム終了のタイミングで

_levelChangeMitame.enabled = YES;//セグメンテッドコントロールをオンにする

これでプレイ中はUISegmentedControlは薄消しになって入力を受け付けなくなりました。\(^o^)/

やはり思い込みは怖いなって話でした。

UISegmentedControl

UISegmentedControlは数個の選択肢から排他的に選択する場合に有効だそうです。

参考にさせて頂いたサイト。
Objective-C Segmented(セグメント) – iscene ページ!

ゲームのLevel、難易度に使用しました。

#import "ViewController.h"
@interface ViewController ()//<UIAlertViewDelegate>
{
    int level;//Levelの設定
}
- (IBAction)levelChange:(UISegmentedControl *)sender;
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //レベルの初期値
    level = 10;
}

#pragma mark - レベルの設定
- (IBAction)levelChange:(UISegmentedControl *)sender {
    switch (sender.selectedSegmentIndex) {
        case 0:
            level = 10;
            _recordHyouji.text = [NSString stringWithFormat:@"%04d",recordCount];//それぞれ表示
            _timeHyouji.text = [NSString stringWithFormat:@"%05.2f",10.00];
            break;
            
        case 1:
            level = 30;
            _recordHyouji.text = [NSString stringWithFormat:@"%04d",recordCount30];//
            _timeHyouji.text = [NSString stringWithFormat:@"%05.2f",30.00];
            break;

        case 2:
            level = 60;
            _recordHyouji.text = [NSString stringWithFormat:@"%04d",recordCount60];//
            _timeHyouji.text = [NSString stringWithFormat:@"%05.2f",60.00];
            break;
    }
}

ボタンを選択すると、選択した番号を持ってaction接続したメソッドへ飛びます。
そこでswitch文でそれぞれにあった動作をさせます。

UIAlertViewの表示

UIAlertViewで検索をかけると、iOS8からUIAlertViewは推奨されなくなりUIAlertControllerになるという記事ばかりひっかかった。

特にSWIFTではそうなのらしい。

とは言え、こっちはまだObjective-cで頑張ってるところだ。

参考にさせて頂いたサイト。
Objective-C AlertView – iscene ページ!

まだデリゲートはよくわかってないが、アラートビューにはアラートビューデリゲートを使うらしい。
アラートを出す書式は出すタイミングで記述してもよいが、別のメソッドにしてみた。

#import "ViewController.h"
@interface ViewController ()//<UIAlertViewDelegate>

#pragma mark - アラートビュー

- (void)alarthyouji
{
    UIAlertView *alart = [[UIAlertView alloc] initWithTitle:@"タイトル"
                                                    message:@"メッセージ"
                                                   delegate:self
                                          cancelButtonTitle:@"キャンセル"
                                          otherButtonTitles:@"ボタン1",@"ボタン2", nil];
    [alart show];
}

- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
            NSLog(@"キャンセル");
            break;
        case 1:
            NSLog(@"動作1");
            break;
        case 2:
            NSLog(@"動作2");
            break;
    }
}

[self alertHyouji];で呼び出せるはず。

それとも他のメソッドからでも[alart show];で呼び出せるのかな?

Implicit conversion loses integer precision: ‘NSUInteger’ (aka ‘unsigned long’) to ‘int’ っていうエラー

前回の記事のNSUserDefaultsを試している時に
データの取り出しで

    recordCount = [defaults integerForKey:@"record"];

と書くと黄色三角で

Implicit conversion loses integer precision: ‘NSUInteger’ (aka ‘unsigned long’) to ‘int’

とエラー表示された。
動かなくはないけどなんか違うよって言われてるみたいだ。

調べてみたところ参考にさせて頂いたサイト。
エラーをやっつけました。│MKProject for iOS
NSInteger型とint型はちょっと違うよって事らしい。

    recordCount = (int)[defaults integerForKey:@"record"];

(int)をつけるとエラーは消えた。

先人の記事が有難いです。(−人−)