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 を使うより感覚的に、わかりやすい。

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

UIViewController のライフサイクルについて

UIViewControllerのライフサイクル - Qiita

にすばらしい説明があった

viewDidUnload とかは、以前はあったようが、途中で消滅している

viewDidUnloadがdeprecatedになった理由を考察 | Cyber Passion for iOS

 


参考 

iOS のイベント駆動をライフサイクルイベントとユーザアクションイベントにわけて理解するhttp://glassonion.hatenablog.com/entry/20120405/1333611664

 

Unwind Segueによる画面遷移

戻り遷移の際に、判定を加えたい。

ネットのサンプルを見ると canPerformUnwindSegueAction を使って判定すれば良いように記述されていたが、試して見ると、例外が発生してしまう。

代わりに shouldPerformSegueWithIdentifier でならできた

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
    // NOを返却すると、戻り遷移はしない
    return YES;
}

参考

[Swift]初心者向け!Segueを使った画面遷移方法http://yuu.1000quu.com/how_to_use_segue

 

[Swift]コードで画面遷移を行う3つの方法http://yuu.1000quu.com/screen_transition_in_swift

StoryboardとSegueの基本 - Kesin's diary

UIDocumentInteractionController が iPadで有効にならない

Deployment device が iPhoneだと正常に起動するが、

Deployment device が iPadだと連携先のメニューが表示されない。

なんで?

iPhoneiPadで選択メニューの表示方法が異なる。

 iPhoneの場合は、中央下に表示されるが、iPadの場合は、座標を指定しないとダメみたい。

トリガーのボタンの右下の座標を基準に、選択メニューを表示するようにしてみた。

- (IBAction)btnOpen:(UIButton *)sender {
    [self fileOpen:@"sample.pdf" ui:sender];
}

-(void)fileOpen:(NSString*)fileName ui:(UIButton*)ui {
    NSURL *url = [NSURL fileURLWithPath:fileName];

    CGRect rect = CGRectMake(ui.frame.origin.x + ui.frame.size.width ,ui.frame.origin.y + ui.frame.size.height,0,0);
    isValid =[_docInteractionController
            presentOpenInMenuFromRect:rect
                               inView:self.view
                             animated:YES];
}

 上記のように実装しても、iPhoneでは相変わらず、下中央に開く

 


参考

ios - UIDocumentInteractionController not appearing on iPad but working on iPhone - Stack Overflow

 

画面遷移

アプリ全体のイベント (〜Will〜は直前、〜Did〜は直後

application

アプリが起動されたとき。AppDelegateに実装。

 

 

applicationWillResignActive   applicationDidEnterBackground

アプリがバックグランドになったとき。 

一時的なデータ保存処理などを記述。

 

 

applicationWIllEnterForground    applicationDidBecomeActive

アプリがバックグランドから戻ってきとき。

一時的に保存しておいたデータを戻す処理などを記述

 

 

applicationWillTerminate

アプリが終了するときの処理を記述

 


画面遷移に関するイベント

viewDidLoad

アプリ起動後、最初に表示する1回目だけ発生。

画面を表示する準備ができたとき。

その画面で最初に表示する処理を記述。

viewWillAppear

画面を表示する直前。表示する度に発生。

viewDidAppear

画面が表示された直後。表示される度に発生。

viewWillDisappear

画面が消える直前、別の画面に切り替わるとき

viewDidDisappear

画面が消えた直後、別の画面に切り替わったとき

prepareFoeSegue

セグエで、別の画面に進む直前


 


プッシュ遷移、ポップ遷移とは、 遷移に伴うアニメーション(トランジション)の一つ


参考

アプリに最適なアニメーション遷移とスピードを考えてみよう!https://blogs.adobe.com/creativestation/web-xd-ui-transition-easing

swift Segueの種類について https://ja.stackoverflow.com/questions/17290/swift-segueの種類について

画面遷移の3パターンhttp://firstiphoneapp.blogspot.jp/2011/12/blog-post.html

 

iOS アプリの構造がどのようになっているか紐解いてみるhttp://glassonion.hatenablog.com/entry/20120507/1336320038

iOS アプリの画面開発の基礎を理解する2http://glassonion.hatenablog.com/entry/20120601/1338477967

 

iOS のイベント駆動をライフサイクルイベントとユーザアクションイベントにわけて理解する http://glassonion.hatenablog.com/entry/20120405/1333611664