「iPhone」カテゴリーアーカイブ

【Objective-C】音楽再生関連のまとめ

諸々調べているのでメモ。

MPMusicPlayerControllerクラス | Second Flush
MPMediaQuery Class Reference | iOS Developer Library — Pre-Release
iOSで、ミュージックライブラリにアクセスして音楽を再生する | nackpan Blog
音楽プレイヤのメソッド(1) | Second Flush
Objective-C – ARC環境下でAVAudioPlayerを使い柔軟かつシンプルにサウンドを再生する方法 – Qiita
プロフェッショナルプログラマー: iOS 音声再生(AVAudioPlayer)
MPMediaEntity Class Reference | iOS Developer Library
iOS – iTunesみたいに再生中の曲のアートワーク(ジャケット写真)に合わせて背景色と文字色を変える – Qiita
Media Player Framework Reference | iOS Developer Library
AddMusic | iOS Developer Library
AVPlayerDemo | iOS Developer Library
[iOS]AVPlayerを使う | nackpan Blog

【Objective-C】UIPageControlのページ切替タイミング

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

前回の投稿絡みで、自前でUIPageControlを追加したときに、ページ数表示更新のタイミングでハマったのでメモ。

要は・・・

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed;
{
  ...
}

このページ切替アニメーションの終了タイミングで更新するのが吉、ということ。

自前のスクリプト載せようと思ったら、要らなくなったんで消した後でした・・・。

【参考】
これからiOS(iPhone)アプリを開発する人々へ: UIPageViewControllerについて

【Objective-C】UIPageViewControllerでUIPageControlが表示されない

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

UIPageViewControllerを使った時に、下記の条件を満たせば自動的にUIPageControl(iPhoneのホーム画面にもある、現在位置を示す○)が表示されるらしい。

・UIPageViewControllerを生成するとき、nitWithTransitionStyle:UIPageViewControllerTransitionStyleScrollになっている。

    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
                               navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                               options:nil];

※self.pageViewControllerは、UIPageViewControllerです。

・ページが戻ったときに呼ばれるハンドラ

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    .....
{

・ページが進んだときに呼ばれるハンドラ

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    .....
{

【参考】
UIPageViewControllerの画面下部に表示されているPageControlを隠す – iOSアプリ開発の逆引き辞典
UIPageViewControllerの使い方 -Tips- – hyoromoのブログ

が、実際に自分で作ってみたら、何も表示されない。散々いろんなケースを疑い、果てはないなら自分でUIPageControlを実装してみたりして試行錯誤した結果、わかったことは・・・

「UIPageControlは表示されているが見えないだけ」

であったことが判明。

UIPageControlはざっくりいうと、

・親ViewにUIPageViewControllerを生成して、subViewとして追加。
・追加されたUIPageViewController.viewに、実際に表示する子Viewを入れ替えることで切替を表示する。

という仕組みになっている。

で、UIPageControlも親Viewに表示されるはずですが、親ViewのbackgroundColorが白(whiteColor)になっていたことが原因でした。
UIPageControlの初期値についての情報は得られなかったのですが、色々試した限りでは。。。

・[UIPageControl currentPageIndicatorTintColor](現在ページの○)>白
・[UIPageControl pageIndicatorTintColor](選択されてないページの○)>白+アルファ値(50%?)
・[UIPageControl backgroundColor](背景色)>白

となっているようです。よって親ViewのbackgroundColorが白だと何も見えない。ただ、あるはずの場所をタップすると動きます(見えないのでタップが可能ということ自体に気づいたのもだいぶ後になってからですが…)。

要するに色を替えて見えるようにしてやればいいけど、UIPageViewについてググっても、UIPageView+UIScrollViewをセットで使うときの話題ばかり。で、ようやく見つけたのがコレ。UIPageViewControllerの中にあるUIPageControlを参照すればいいようです。

    //ページコントロール(色を変更する)
    UIPageControl* proxy = [UIPageControl appearanceWhenContainedIn:[self.pageViewController class], nil];
    
//    NSLog(@"setPageIndicatorTintColor >> %@",[proxy pageIndicatorTintColor]);
//    NSLog(@"currentPageIndicatorTintColor >> %@",[proxy currentPageIndicatorTintColor]);
//    NSLog(@"backgroundColor >> %@",[proxy backgroundColor]);
    
    [proxy setPageIndicatorTintColor:[UIColor lightGrayColor]];
    [proxy setCurrentPageIndicatorTintColor:[UIColor blackColor]];
    [proxy setBackgroundColor:[UIColor whiteColor]];

※self.pageViewControllerは、UIPageViewControllerです。

ちなみにコメントになっているNSLogでデフォルトの色を確認しようとしたのだけれど、(null)しか返ってきませんでした。何でだろう?

【参考】
storyboard – iOS Page based template, regarding UIPageViewController and UIPageControl color of the dots – Stack Overflow

これでようやくUIPageControlが表示されました。左右スクロールによる表示制御やタップしたときの挙動は、デフォルトで設定されるようで、UIPageControlについて書いたコードは、上の色替えの部分のみです。

更に、デフォルトだとUIPageControlの位置がかなり下になるので、UIPageViewController.viewの高さを削ってやると、もうちょっと上の位置になります。

- (void)viewDidLoad
{
    ....
    // Change the size of page view controller
    self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30);
    ....
{

最後に一応、コードを載せておきます。
ここでは親クラス(HelpViewController)と子クラス(DetailViewController)を使っています。
子クラス(DetailViewController)には・・・

@property NSUInteger pageIndex;
@property NSString *titleText;
@property NSString *captionText;
@property NSString *imageFile;

のプロパティがあって、生成時に表示する情報を渡しています。

・HelpViewController.h


#import <UIKit/UIKit.h>
#import "DetailViewController.h"

@interface HelpViewController : UIViewController<UIPageViewControllerDataSource,UIPageViewControllerDelegate>

@property (strong, nonatomic) UIPageViewController *pageViewController;
@property (strong, nonatomic) NSArray *pageTitles;
@property (strong, nonatomic) NSArray *pageImages;

@end

・HelpViewController.m

#import "HelpViewController.h"

@interface HelpViewController ()
{
    NSMutableArray *captionArray;
    NSMutableArray *imageArray;
    NSInteger currentPageIndex;
}

@end

@implementation HelpViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //----
    
    //タイトル設定
    
    self.navigationItem.title = NSLocalizedString(@"conf_use", NULL);
    
    // テキストを設定する
    captionArray = [[NSMutableArray alloc] init];
    [captionArray addObject:NSLocalizedString(@"use_caption1", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption3", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption4", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption5", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption6", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption7", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption8", NULL)];
    [captionArray addObject:NSLocalizedString(@"use_caption9", NULL)];
    
    //
    // 画像ファイル名名を設定する
    imageArray = [[NSMutableArray alloc] init];
    [imageArray addObject:NSLocalizedString(@"help_img01", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img03", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img04", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img05", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img06", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img07", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img08", NULL)];
    [imageArray addObject:NSLocalizedString(@"help_img09", NULL)];

    // UIPageViewControllerを生成
    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
                               navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                               options:nil];
    
    self.pageViewController.dataSource = self;
    self.pageViewController.delegate = self;
    
    DetailViewController *startingViewController = [self viewControllerAtIndex:0];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    
    // UIPageViewControllerのサイズを変更(UIPageControlを上に表示する為)
    self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30);
    
    [self addChildViewController:_pageViewController];
    [self.view addSubview:_pageViewController.view];
    [self.pageViewController didMoveToParentViewController:self];
    
    //ページコントロール(色を変更する)
    UIPageControl* proxy = [UIPageControl appearanceWhenContainedIn:[self.pageViewController class], nil];
    
    [proxy setPageIndicatorTintColor:[UIColor lightGrayColor]];
    [proxy setCurrentPageIndicatorTintColor:[UIColor blackColor]];
    [proxy setBackgroundColor:[UIColor whiteColor]];
    
}

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

- (DetailViewController *)viewControllerAtIndex:(NSUInteger)index
{
    if (([captionArray count] == 0) || (index >= [captionArray count])) {
        return nil;
    }
    
    // 新しいページのviewを生成
    DetailViewController *DetailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
    DetailViewController.imageFile = imageArray[index];
    DetailViewController.captionText = captionArray[index];
    DetailViewController.titleText = NSLocalizedString(@"conf_use", NULL);

    DetailViewController.pageIndex = index;
    
    return DetailViewController;
}

#pragma mark - Page View Controller Data Source

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = ((DetailViewController*) viewController).pageIndex;
    
    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }
    
    index--;

    return [self viewControllerAtIndex:index];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = ((DetailViewController*) viewController).pageIndex;
    
    if ((index >= [captionArray count]) || (index == NSNotFound)) {
        return nil;
    }
    
    index++;
    if (index == [captionArray count]) {
        return nil;
    }
    
    return [self viewControllerAtIndex:index];
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
    return [captionArray count];
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
    return 0;
}

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    if(completed){
        DetailViewController *vc =[self.pageViewController.viewControllers lastObject];
        currentPageIndex =  vc.pageIndex;
    }
}


@end

・DetailViewController.h

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController
    @property (weak, nonatomic) IBOutlet UITextView *caption;
    @property (weak, nonatomic) IBOutlet UIImageView *helpImage;

@property NSUInteger pageIndex;
@property NSString *titleText;
@property NSString *captionText;
@property NSString *imageFile;

@end

・DetailViewController.m

#import "DetailViewController.h"

@interface DetailViewController ()

@end

@implementation DetailViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    _helpImage.image = [UIImage imageNamed:self.imageFile];
    self.title = self.titleText;
    _caption.text = self.captionText;
}

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

@end

あまりに単純な話ですが、同じような目に遭う人もいるかもしれないのでメモとして。

【Objective-C】アプリ内保存した画像のパスがpathForResourceで取れない(解決編)

【追記】2014.9.13 3:00
この方法はあくまで「アプリ内保存した画像のパス」の話で、Xcode上で最初から登録している画像には当てはまりません。パスに「Documents」ディレクトリが含まれないためです。

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

前回の解決編です。

JBOYSOFT JunjiSuzukiさんに「NSSearchPathForDirectoriesInDomains を使うのもいいかも」との助言を受けて、描いてみたコードがこれ。NSSearchPathForDirectoriesInDomainsでディレクトリのパスを取ってきて、保存しているファイル名と組み合わせて、自前でパスを作っている。

    NSArray *paths = NSSearchPathForDirectoriesInDomains(
                                                         NSDocumentDirectory,
                                                         NSUserDomainMask, YES);
    
    NSArray *ph = [select_name componentsSeparatedByString:@"/"];
    NSString *fn = [ph objectAtIndex:ph.count-1];
    
    NSLog(@"paths >> %@",paths);
    NSLog(@"fn >> %@",fn);
    
    path = [NSString stringWithFormat:@"%@/%@",[paths objectAtIndex:0],fn];
    
    NSLog(@"path >> %@",path);

    iconImage = [[UIImage alloc] initWithContentsOfFile:path];

これだと既存のものも、起動後に保存したものも、どちらも問題なく参照出来る!NSLogによるトレースはこちら。

paths >> (
    "/var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/Documents"
)
fn >> icon20140913003532.png
path >> /var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/Documents/icon20140913003532.png

気になったので、前回描いたコードで取得されるパスを確認してみる。前回のコードはコレ。

    NSArray *phrases = [imageName componentsSeparatedByString:@".png"];
    NSString *filename = [phrases objectAtIndex:0];
    NSString *path= [[NSBundle mainBundle] pathForResource:filename ofType:@"png"];
    
    //アプリ内保存した直後の画像は、path が nullになる
    NSLog(@"path >> %@",path);
    
    //保存直後の画像はNSBundleでパスが取れないための対処(アプリが再起動しないとダメみたい)
    UIImage *iconImage;
    
    if (path == NULL) {
        iconImage = [UIImage imageNamed:imageName];
        
    } else {
        iconImage = [[UIImage alloc] initWithContentsOfFile:path];
    }

※ imageNameには、”../Documents/icon20140912171442.png”のようなパスが入っている。

アプリ起動前に保存されている画像について、NSLogで表示されるパスを見ると・・・

path >> /var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/xxxxxx.app/../Documents/icon20140913003017.png

と、アプリ名(xxxxxx.app/../)がはさまってる。この違いは何?NSBundleだとこうなるの?

更に、冒頭の修正コードをアプリ名(xxxxxx.app/../)がはさまってるパスに変更して参照してみる。

    NSArray *paths = NSSearchPathForDirectoriesInDomains(
                                                         NSDocumentDirectory,
                                                         NSUserDomainMask, YES);
    
    NSArray *ph = [select_name componentsSeparatedByString:@"/"];
    NSString *fn = [ph objectAtIndex:ph.count-1];
    
    NSLog(@"paths >> %@",paths);
    NSLog(@"fn >> %@",fn);
    
    NSArray *paths2 = [[paths objectAtIndex:0] componentsSeparatedByString:@"Documents"];
    path = [NSString stringWithFormat:@"%@iconFaceCam.app/%@",[paths2 objectAtIndex:0],select_name];
    
    NSLog(@"path >> %@",path);

    iconImage = [[UIImage alloc] initWithContentsOfFile:path];

NSLogの出力結果がこれ。

paths >> (
    "/var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/Documents"
)
fn >> icon20140913012801.png
path >> /var/mobile/Applications/BB4E2366-816D-427F-8F8B-FF836EB58AB8/xxxxxx.app/../Documents/icon20140913012801.png

動作としては、こちらでも問題なく動きました。

で、結論としては、アプリ内保存のファイル参照では・・・

・NSSearchPathForDirectoriesInDomainsでドキュメントディレクトリを取得する。
・ドキュメントディレクトリ+ファイル名でパスを生成する。
・生成したパスを使って、initWithContentsOfFileで参照する。

ということになるんだけれど、そもそも何で・・・

[[NSBundle mainBundle] pathForResource:filename ofType:@”png”]

でパスが取得できないのか、がわからずモヤモヤします…。

とりあえずは余計なifとか要らなくなったので、よしとして先に進みます。
JBOYSOFT JunjiSuzukiさんに感謝。

【参考】
iOS でデータを永続化する方法 – A Day In The Life

【Objective-C】アプリ内保存した画像のパスがpathForResourceで取れない

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

以前、iOSアプリ内に画像を保存するという記事を書いて、その後、保存した画像の参照を[UIImage imageNamed]から、[[NSBundle mainBundle] pathForResource:]に変更したら、保存直後の画像参照ができなくなった。

で、いろいろテストしてみると、一度アプリを終了してからの画像は参照出来るので、NSBundleはアプリ起動時の情報しか持っていないのではないかと思われます。とりあえず動かすために、こんなコードを書いて回避してるんだけど、NSBundleを強制的に更新するとか、何かいい方法はないでしょうか?NSBundleを調べてみたけどよくわからなかったので。

    NSArray *phrases = [imageName componentsSeparatedByString:@".png"];
    NSString *filename = [phrases objectAtIndex:0];
    NSString *path= [[NSBundle mainBundle] pathForResource:filename ofType:@"png"];
    
    //アプリ内保存した直後の画像は、path が nullになる
    NSLog(@"path >> %@",path);
    
    //保存直後の画像はNSBundleでパスが取れないための対処(アプリが再起動しないとダメみたい)
    UIImage *iconImage;
    
    if (path == NULL) {
        iconImage = [UIImage imageNamed:imageName];
        
    } else {
        iconImage = [[UIImage alloc] initWithContentsOfFile:path];
    }

※ imageNameには、”../Documents/icon20140912171442.png”のようなパスが入っている。

【参考】
NSBundleクラス | Second Flush

【Objective-C】特定のUIGestureRecognizerを削除する

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

一時的にUIGestureRecognizerをセットして、不要になったら削除するという場合のメモ。例えば・・・

・UITapGestureRecognizerはデフォルトで常に設定
・ある条件で、UIPanGestureRecognizerを追加
・不要になったら、UIPanGestureRecognizerだけを削除

というような場合。

    for(UIGestureRecognizer *gesture in [selectIconView gestureRecognizers]) {
        NSLog(@" isClass UITapGestureRecognizer!! %d", [gesture isKindOfClass:[UITapGestureRecognizer class]]);
        NSLog(@" isClass UIPanGestureRecognizer!! %d", [gesture isKindOfClass:[UIPanGestureRecognizer class]]);
    }

※ selectIconViewは、UIGestureRecognizerを設定したUIImageView。

こんな感じで「isKindOfClass」で判定可能。

で、実際にやりたかったのは、こんな感じ。

    for(UIGestureRecognizer *gesture in [selectIconView gestureRecognizers]) {
        
        // UIPanGestureRecognizerのみ削除
        if([gesture isKindOfClass:[UIPanGestureRecognizer class]]) {
            [selectIconView removeGestureRecognizer:gesture];
        }
    }

【参考】
aideal.jp UIGestureRecognizer
gesture recognizerを全削除する – 日々精進
UIGestureRecognizerクラス | Second Flush
Objective-C – UIViewからUIGestureRecognizerを削除 – Qiita
isKindOfClassとisMemberOfClassってなにが違うねん | S4U -smile for you-

【Objective-C】UITableViewCellに入れたUISwitchから親セルを参照

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

UITableViewCellをカスタマイズして、UISwitchを入れてみた。これはそんなに難しくない。こんな感じで。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    
    // cellを選択不可にする
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    // UISwitchを作成
    UISwitch *sw = [[UISwitch alloc] initWithFrame:CGRectZero];
    
    // UISwitchのタップ動作を指定
    [sw addTarget:self action:@selector(tapSwich:) forControlEvents:UIControlEventTouchUpInside];
    
    // UISwitchをaccessoryViewに代入
    cell.accessoryView = sw;
    
    cell.textLabel.text = sw_name;
    
    return cell;
}

【参考】
[XCODE] UITableViewCellに、様々なコントロール要素をのせて表示する方法 – YoheiM.NET
UITableViewCell の accessoryView を使うと少し楽 (フェンリル | デベロッパーズブログ)

で、UISwitchをタップしたときに呼ばれるtapSwichで「何番目のセルか?」(indexPath.row)を取得しようとしてハマった。
最初は「UITableViewCellに入れたんだから、その親でしょ?」とこんな感じに書いたけど取得できず。

    UITableViewCell *cell = (UITableViewCell *)[sw superview];
    int row = (int)[self.tableView indexPathForCell:cell].row;

そこで階層を調べるために、こんなふうに書いてみた。

    NSObject *t = (UITableViewCell *)[sw superview];
    NSObject *tt = (UITableViewCell *)[[sw superview] superview];
    NSObject *ttt = (UITableViewCell *)[[[sw superview] superview] superview];
    NSObject *tttt = (UITableViewCell *)[[[[sw superview] superview] superview] superview];
    
    NSLog(@"--switch  >> %@ , \n%@ , \n%@, \n%@",t,tt,ttt,tttt);

その出力結果がコレ(見やすいように一部省略)

2014-09-02 01:50:00.953 iconFaceCam[3017:60b] --switch  >> 
<UITableViewCellScrollView: ...> , 
<UITableViewCell: ...> , 
<UITableViewWrapperView: ...>, 
<UITableView: ...>

UISwitchとUITableViewCellの間に、UITableViewCellScrollViewというのが入ってるらしい。
そこで、こんな感じに書いて参照出来ました。

-(void)tapSwich:(id)sender
{
    UISwitch *sw = (UISwitch *)sender;
    
    UITableViewCell *cell = (UITableViewCell *)[[sw superview] superview];
    int row = (int)[self.tableView indexPathForCell:cell].row;
    
    // UISwitch:初期値を指定
    switch (row) {
        case 0:
            .....;            
            break;
        case 1:
            .....
            break;
        case 2:
            break;
            
        default:
            break;
    }
}

調べてみたら、この階層はiOS7になって変更されているらしいので、iOS6ではまた違うらしい。
詳しくは以下のリンクへ。

iOS7 では UITableViewCell の subviews階層が変更されている | objc-Lovers

【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を特定の文字で分割する方法