【Objective-C】日付を24時間表示で取得する際の注意点

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】

日付を24時間表示で取得するには、LocaleをUSに設定しないと端末設定で結果が変わるらしい。

で、こんな感じで関数を書いてみた。

//現在の年月日時分秒を取得
-(NSString *)getCurrentTime
{
    NSDate *nowdate = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyyMMddHHmmss"];
    
    //24時間表示にするためLocaleはUSにする
    [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"US"]];
    NSString *dateString = [formatter stringFromDate:nowdate];
    
    return dateString;
}

【参考】
NSDateで現在の日付を取得する | イリテク株式会社
NSDateFormatter – 文字列と日付の変換 – 強火で進め
日本語環境では、NSDateFormatterでフォーマットした日付がおかしい – 24/7 twenty-four seven

【Objective-C】ModalとNavigationの画面遷移方法の違い

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】

Storyboardの画面リンク(Segue)を使わずに、コードで画面遷移を書いていてハマったのでメモ。

・ナビゲーション(Navigation/UITableViewControllerなどで使う、NavigationBarが出てくる画面遷移)

    //画面を遷移(※confVCは表示するViewCOntroller)
    [self.navigationController pushViewController:confVC animated:YES];

    //元画面に戻る
    [self.navigationController popViewControllerAnimated:YES];

・モーダル(Modal/現在のViewに重なるように表示する画面遷移)

    //画面を遷移(※confVCは表示するViewCOntroller)
    [self presentViewController:configurationVC animated:YES completion:nil];

    //元画面に戻る
    [self dismissViewControllerAnimated:YES completion:nil];

この2つをごっちゃにしていてハマりました。どのViewControllerでも、ナビゲーション(Navigation)の方法ならきちんとNavigationBarが表示されて戻るボタンが自動でつきます。

最初はUITableViewControllerだけNavigationBarが出なくて調べていたら、こんな基本的なことだたっという・・。

【参考】
iOS アプリの画面開発の基礎を理解する – A Day In The Life
iPhoneプログラミング入門「モーダルビュー1」
Objective-C – モーダルビューを出したり消したり – Qiita
yuki0n0 高校生アプリ開発者のブログ: storyboardで作った画面をコードで画面遷移

だんだん作り込んでくると、基本的な画面のレイアウト(固定部分)はStoryboardを使って、画面遷移やボタン配置など可変になる部分はコードで制御する方がいいかなと思っていて、Storyboardの画面リンク(Segue)を全部削除してコードで書き換えてます。

【Objective-C】NSStringを特定の文字列で分割して配列化

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】

まあ、ActionScriptでいうところの、String.split(“/”)をやりたかったのですが、意外に探すのに手こずったのでメモ。

// ファイルパスを「/」で分割して、削除ファイル名を取り出す
NSString *test = @"../Documents/icon20140819002020.jpg";
NSArray *phrases = [test componentsSeparatedByString:@"/"];
NSString *filename = [phrases objectAtIndex:phrases.count-1];
NSLog(@" --delete file >> %@",filename);

で、結果がこちら。

--delete file >> icon20140819002020.jpg

参考:YoheiM.NET|[XCODE] NSStringを特定の文字で分割する方法

【Objective-C】UICollectionViewCellの選択表示

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】

UICollectionViewCellで選択表示をさせようと思ってハマったのでメモ。

参考:Collection View プログラミングガイド(iOS用)【PDF】
※P25〜P28あたり。

選択状態をコードで制御するには・・・

たとえば、セルの選択状態をアプリケーション側で描画したい場合は、selectedBackgroundViewプロパティをnilにし、デリゲートオブジェクトに、外観を変更する処理を組み込んでください。
collectionView:didSelectItemAtIndexPath:メソッドに外観を変更する処理、
collectionView:didDeselectItemAtIndexPath:メソッドに元の状態に戻す処理を実装します。

ということらしいので、コードを書いてみた。

//UICollectionViewCell:編集
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell;
    
    cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell1" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor whiteColor];
    cell.selectedBackgroundView = nil;
    
    //(中略)

    return cell;
}

//
-(void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"選択した %@",indexPath);
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    cell.backgroundColor = [UIColor redColor];
}

-(void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"選択解除した %@",indexPath);
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    cell.backgroundColor = [UIColor whiteColor];
}

これだとタップしている間は、背景色が赤に変わるけれど、指を離すと白に戻ってしまう。

で、更に資料を読んでみると・・・

図 2-3に、未選択状態のセルにユーザがタッチしたときに発生する、一連の動作を示します。最初の「タッチダウン」イベントを受けて、コレクションビューはセルの「強調表示」状態をYESにします。もっとも、自動的にセルの外観に反映されるわけではありません。その後、「タッチアップ」イベントが発生すると、「強調表示」状態はNOに戻り、「選択」状態はYESに変わります。ユーザが選択状態を変更すると、コレクションビューはセルのselectedBackgroundViewプロパティに設定されているビューを表示します。コレクションビューが関与してセルの外観を変えるのは、この場合に限ります。ほかの視覚効果はデリゲートオブジェクトが行わなければなりません。

つまり、指を離すと選択状態にはなるものの didUnhighlightItemAtIndexPathが呼ばれて、表示が戻ってしまう・・・ということらしい。

結局、didHighlightItemAtIndexPathとdidUnhighlightItemAtIndexPathは使わず、以下の様に書いて解決。

//UICollectionViewCell:編集
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell;
    
    cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell1" forIndexPath:indexPath];
    
    //通常の背景
    UIView* backgroundView = [[UIView alloc] initWithFrame:cell.bounds];
    cell.backgroundColor = [UIColor whiteColor];
    cell.backgroundView = backgroundView;
    
    //選択時の背景
    UIView* selectedBGView = [[UIView alloc] initWithFrame:cell.bounds];
    selectedBGView.backgroundColor = [UIColor redColor];
    cell.selectedBackgroundView = selectedBGView;
    
    //(中略)
    
    return cell;
}

最初のコードで、選択時のイベントハンドラ(didSelectItemAtIndexPath)で選択済表示に変えることもできるけど、それだと選択済項目の表示を戻してやる処理が必要になるので、単一選択ではこれが一番簡単かなと。

【Objective-C】UIBarButtonItemの右ボタンを動的に差し替える

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】

カメラロールでサムネイル表示したときに、右上に出る「選択」>「キャンセル」の切替と同じやつです。これってViewは切り換えてないよなあと思ったので、ボタンの差し替えをテストしてみました。

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //削除ボタンを追加
    UIBarButtonItem *delButton = [[UIBarButtonItem alloc]
                                  initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
                                                                               target:self
                                                                               action:@selector(delButtonDidPush:)];
    

    self.navigationItem.rightBarButtonItem = delButton;
}

-(void)delButtonDidPush:(UIBarButtonItem *)button
{
    NSLog(@" -- trash!!");
    
    //
    UIBarButtonItem *canelButton = [[UIBarButtonItem alloc]
                                    initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
                                    target:self
                                    action:@selector(cancelButtonDidPush:)];
    self.navigationItem.rightBarButtonItem = canelButton;
}

-(void)cancelButtonDidPush:(UIBarButtonItem *)button
{
    NSLog(@" -- cancel!!");
    
    //削除ボタンを追加
    UIBarButtonItem *delButton = [[UIBarButtonItem alloc]
                                  initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
                                  target:self
                                  action:@selector(delButtonDidPush:)];
    
    
    self.navigationItem.rightBarButtonItem = delButton;
    
}

これでちゃんと動いてるし、タップのイベントも片方しか出てこないので、たぶんいいはず。
UIToolBarについては、こんな記事が。

なんとなく|UINavigationController の UIToolBar で Button 表示を切り替えたいメモ

たぶんnavigationItem.rightBarButtonItemは1つしか置けないので、重なったりすることはないのでは?と推測。

【Xcode】ARC配下でのメモリ管理関連リンク

ARC配下でのメモリ管理関連リンク。あとで読む用。

Second Flush ARCへの移行のリリースノート
infinite loop 技術ブログ Objective-Cのメモリ管理おさらいと解放tips
私的メモ [Objective-C] メモリリークをチェックする
ARCを使用したメモリ管理の基礎
ARC環境でメモリが枯渇するケース
sirochro Objective-C: これで解決!ARCを使用しReceived memory warningが出た時の対処方法
Developers.IO [Xcode 5] Xcode 5のデバッグ機能 “Debug gauges”
Instruments ユーザガイド[PDF]
【iOS/Mac開発】超サクサクアプリへの必須ツール Instruments を使いこなそう