アイコンバッチ

アイコンバッチを表示する方法を検索すると以下の用法が表示される 

[UIApplication sharedApplication].applicationIconBadgeNumber = 5;

 この通りやっても、表示されなかった。iOS9からは通知に関する設定を行わないといけなくなったようだ。


IOS9からは、ユーザーの認証が必要になったみただ。

下記のコードをAppDelegate.m 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 配下に実装する必要がある。

UIUserNotificationType types = UIUserNotificationTypeBadge;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[application registerUserNotificationSettings:settings];

 初回実行時に、「〜( アプリ名)〜は通知を送信します

よろしいですか?」が表示されるようになる。許可する/しない の設定は、

後から変更できる。設定→通知→該当のアプリ。通知を許可をオン、Appアイコンにバッチを表示をオン。

これで、アイコンにバッチが表示されるようにはなったけど、

iOS10からは、非推奨のメソッドになっている!?


 iOS10でコンパイルエラーが出ないように書き直してみた。こんなのでいいのかなぁ?

AppDelegate.m

 

#import <UserNotifications/UserNotifications.h>   を冒頭で追加する必要あり



-
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter]; [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted){ NSLog(@"承認された"); }else{ NSLog(@"承認されなかった"); } }]; return YES; }

この例の場合、アイコンバッチだけの確認になっています。

[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge + 

UNAuthorizationOptionAlert

)  とすれば、複数の条件が申請できるみたい。

 

granted には、許可に認否結果が渡ってくる。

初回許可しても、後々設定から不許可にした場合も、grantedには NOが渡ってくる。


バッチの数量はいつくまで、表示できるのか?

6桁まではそのまま表示される。

7桁以上の場合、中間の桁が ... 表示となり省略されるようだ。

f:id:nabe_shodai:20170619000247p:plain  f:id:nabe_shodai:20170619000300p:plain

 


参考

iOS9でバッジが表示されない時の対処法
https://trueman-developer.blogspot.jp/2015/12/ios9.html

 

iOS User Notifications framework」シリーズまとめhttp://dev.classmethod.jp/smartphone/iphone/user-notifications-framework-16/

 

iOS 10 User Notifications Framework実装まとめhttp://qiita.com/mshrwtnb/items/3135e931eedc97479bb5

アイコン

iOS用のアイコンを設定してみたい。

適当なサイズのものを当てはめると、

〜 Assets.xcassets: The app icon set named "AppIcon" did not have any applicable content.

ビルド実行で上記のようなメッセージ出てしまうので、正しいサイズのアイコンを適用する必要があるようだ。

 

異なるサイズのアイコンを用意するのに、便利なwebページがあった。

https://resizeappicon.com

アップした画像ファイルを、各種サイズに変換してくれる。

アップする画像ファイルは、PNG形式で、正方形でなければならないようだ。

 

2x  20pt は 40☓40px のファイル

3x  20pt は 60☓60px のファイル

2x  29pt は 58☓58px のファイル

3x  29pt は 87☓87px のファイル

・・・

をそれぞれ適用すれば良いようだ。

 

macのプレビューからもリサイズはできる。

[メニューバー]→[ツール]→[サイズを調整]

ピクセル指定で、縦、横を設定すればよい

f:id:nabe_shodai:20170622090639p:plain

 

 

クラスのサンプル

//

//  Person.h

//  クラスの基本

//

//  Created by shodai on 2017/06/15.

//  Copyright © 2017 Mycompany. All rights reserved.

//

 

#import <Foundation/Foundation.h>

 

@interface Person : NSObject

 

//この1行だけで、public なアクセサが生成されている(read/write)

@property NSString* name;

 

//この1行だけで、public なアクセサが生成されている(read)

@property (readonly) NSString* sex;

 

 

#pragma mark Protected Methods

-(NSInteger)coutup;

    

@end

 


//

//  Person.m

//  クラスの基本

//

//  Created by shodai on 2017/06/15.

//  Copyright © 2017 Mycompany. All rights reserved.

 

/*

 参考

 https://www.ecoop.net/memo/archives/objective-c-property-basics.html

 http://qiita.com/a_ishidaaa/items/6461f62a1a12208b0c50

 http://qiita.com/yuky_az/items/f2c3db2796d0a73dfde2

 http://adragoona.hatenablog.com/entry/2014/06/11/182527

 */

 

//

 

#import "Person.h"

 

 

 

@implementation Person{

    

    //完全にプライベートな扱いとなるインスタンス変数

    NSInteger count;

}

 

-(id)init{

    

    self = [super init];

 

    _sex = @"man";

    

    return self;

    

}

 

 

-(NSInteger)coutup{

    

    count++;

    

    return count;

    

}

    

 

 

@end


クラスを利用する側

    Person* person = [[Person alloc] init ];

 

    NSLog(@"%@",person.sex);

    NSLog(@"%@",[person sex]);

    

    //person.sex = @"woman"; コンパイルエラーになる

    

    person.name = @"aaa";

    

    NSLog(@"%@",person.name);

    NSLog(@"%@",[person name]);

 

    

    [person setName:@"bbb"];

 

    NSLog(@"%@",person.name);

    NSLog(@"%@",[person name]);

 

    NSLog(@"%ld",[person coutup]);

 

 

property ぷろぱてぃ


@property (nonatomic,copy) NSString* name;

———————
atomic
省略時のデフォルト。synchronizedでスレッドセーフにしたgetter,setterを生成します。

nonatomic
スレッドセーフでない単純なgetter,setterを生成します。iOSではパフォーマンスの問題からほとんどの場合nonatomicにすべきです。

———————

readwrite
デフォルト。getter/setter両方を生成します。


readonly
getterのみ生成します。

———————

geter=メソッド名
getterの名前を設定する。デフォルトはプロパティ名と同じ。BOOL 型のプロパティの名前を is〜とすると分かりやすくなります。

seter=メソッド名
setterの名前を設定する。デフォルトは「setプロパティ名」。あまり使われることはありません。

———————

assign
非オブジェクト型のデフォルト。NSIntegerなど値型、C由来の型など、メモリ管理が必要ないものに使用します。オブジェクト型の場合はassignでなくweakかunsafe_unretainedが推奨されます。

strong
オブジェクト型のARC環境デフォルト。setterで代入前のものをreleaseし、新たに代入するものをretainします。非オブジェクト型には使用できません。

retain
strongと全く同じです(参考:Transitioning to ARC Release Notes)

weak
オブジェクト型の非ARC環境デフォルト。代入時にretain/releaseを行いません。メモリアクセスエラーを避けるため参照先が解放された時はnilになります。strongと同様、非オブジェクト型には使用できません。

unsafe_unretained
weakと似ていますが、releaseされてもnilになりません。assignと同じですが、こちらはオブジェクト型を対象としています。

copy
retain/releaseする点はstrongと同じですが、代入時にsetterで引数のオブジェクトをretainせずに、新たなオブジェクトとしてコピー(_value = [value copy])してからretainします。用途としてはNSStringなどmutableな型(NSMutableString)が子クラスとして存在するものについて、代入後に外部からの値の変更を防ぐためにstrongの代わりにcopyを使用します。

 

Webからファイルを取得して保存

URL指定でファイルを取得したい場合、従来は以下の方法で取得できたが NSURLConnectionは deprecated(非推奨) となった

//取得先のコンテンツのURLを設定
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/test/mydata.txt"];
];
    
//リクエストを作成
NSURLRequest *req = [NSURLRequest requestWithURL:url];
//レスポンスを作成
NSHTTPURLResponse *res;
NSData *contents = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:nil];

// ファイルへ書き出す
NSString *path = [NSString stringWithFormat:@"%@/mydata.txt", NSHomeDirectory()];
BOOL ret = [contents writeToFile:path atomically:YES];

NSURLSession dataTaskWithRequest:completionHandler に変更せよとのこと

// NSURLSession を使った方式

//NSURLSessionDataTaskは非同期タイプなので、待ち合わせを行う為に、セマホを使う
// 初期値 0で作成しているので、初回は必ず、待ち状態になる。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

//リクエストオブジェクトを作成
NSURL *url = [NSURL URLWithString:@"http://uid:password@localhost/test_login_basic/test.txt"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];


/*
    NSURLSessionConfiguration
    データをアップロードおよびダウンロードするときに使用する動作およびポリシーを定義します。
    データをアップロードまたはダウンロードするときは、常に設定オブジェクトを作成する必要があります。
    このオブジェクトを使用して、タイムアウト値、キャッシュポリシー、接続要件、
    およびNSURLSessionオブジェクトで使用する他の種類の情報を構成します。
    
    ephemeralSessionConfiguration
    エフェメラルセッション構成オブジェクト
    キャッシュ、Cookie、または資格情報に永続ストレージを使用しないセッション構成を返します。
 */
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];


NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

/*
 dataTaskWithRequest:completionHandler:
 指定されたURL要求オブジェクトに基づいてURLの内容を取得し、完了時にハンドラを呼び出すタスクを作成します。
 このタスクは、応答とデータ配信のためにメソッドを委譲するための呼び出しをバイパスし、
 代わりに結果のNSData、NSURLResponse、およびNSErrorオブジェクトを補完ハンドラ内に提供します。
 ただし、認証の問題を処理する代理メソッドは引き続き呼び出されます。
 引数
 completionHandler
 ロード要求が完了したときに呼び出す完了ハンドラ。
 このハンドラはデリゲートキューで実行されます。
 nilを渡すと、タスクが完了するとセッションデリゲートメソッドだけが呼び出され、
 このメソッドはdataTaskWithRequest:メソッドと同等になります。
 */

NSURLSessionDataTask *task = [session dataTaskWithRequest:urlRequest
                                        completionHandler:^(NSData * _Nullable data,
                                                            NSURLResponse * _Nullable response,
                                                            NSError * _Nullable error)
                              {
                                  
                                  NSLog(@"did finish download.\n%@", response.URL);
                                  
                                  if (error) {
                                      NSLog(@"%@", error);
                                      dispatch_semaphore_signal(semaphore);
                                      return;
                                  }
                                  
                                  NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                                  if (httpResponse.statusCode != 200) {
                                      dispatch_semaphore_signal(semaphore);
                                      return;
                                  }
                                  
                                  
                                  NSString *path = [NSString stringWithFormat:@"%@/mydata.txt", NSHomeDirectory()];
                                  BOOL ret = [data writeToFile:path atomically:YES];
                                  if ( ret == YES ) {
                                      NSLog(@"ファイルがダウンロードできました");
                                  } else {
                                      NSLog(@"ダウンロードに失敗しました");
                                  }

                                  /*セマホを+1する*/
                                  dispatch_semaphore_signal(semaphore);
                                  
                              }];

/*タスクが中断している場合は、タスクを再開します。*/
[task resume];

/*
    #define DISPATCH_TIME_FOREVER (~0ull)
    セマホが1になるまで待ち合わせをする。永遠に。
 */
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

NSLog(@"compliate");


参考

http://Cat.jp.as.criteo.com

NSURLConnection から NSURLSession への移行例 - Qiita

Blocksを活用する事例と小技 - Qiita

配列 いろいろ

NSArrayからイテレータ的に値を取得

NSArray* bars = arrayWithObjects:bar1,bar2, nil];

NSEnumerator* eratorBar=[ bars objectEnumerator];
    
NSDictionary* aBar;
while (aBar = [eratorBar nextObject]) {
    NSLog(@"%@", [aBar objectForKey:@"key1" ]);
    NSLog(@"%@", [aBar objectForKey:@"key2" ]);
}

 


参考

http://libro.tuyano.com/index3?id=560003&page=6

http://libro.tuyano.com/index3?id=560003&page=6

 

segueを使わないで画面遷移

view1からview2に遷移する場合

ViewController1.m

- (IBAction)btnPage2:(UIButton *)sender {
    UIStoryboard* myStoryboard = self.storyboard;

    ViewController2* viewController2 = [myStoryboard instantiateViewControllerWithIdentifier:@"view2"];

    viewController2.dataString = @"aaa";
    
    [self presentViewController:viewController2 animated:YES completion:nil];
}

 

view2からの戻り遷移

ViewController2.m

- (IBAction)btnBack:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

 

ポイント

ViewControllerのIDは事前に設定しておく必要あり。

ボタンのクリックイベントとメソッドの紐付けは、control+ドラッグで行なっている。

遷移したいタイミングで、遷移が可能なので、segue を使うより感覚的に、わかりやすい。

思ったよりも簡単だった。