UIScrollView に背景画像を設定する

#import <UIKit/UIKit.h>
@interface UIScrollViewWithBGImage : UIViewController <UIScrollViewDelegate>
{
    UIImageView *backgroundImageView;
}

@property (nonatomic, retain) UIScrollView *scrollView;

@end

上のようなヘッダーにおいて、scrollViewプロパティに背景画像を追加する事を考える。

その1

簡単なのは、viewをaddした後に、次のように呼ぶこと。

     [self.view bringSubviewToFront:_scrollView];
     for(UIView *subview in [_scrollView subviews])
     {
          [_scrollView bringSubviewToFront:subview];
     }

ただこの方法だと、viewがたくさんあったときに、最後にほぼ全てのviewのz-indexを調整しなくてはならなくなる。

ということで

その2

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view./* initialize */    
    [self.view addSubview:_scrollView];
    [_scrollView addSubview:backgroundImageView];
}

#pragma mark -
#pragma mark UIScrollView delegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect scrolledRect;
    scrolledRect.origin = CGPointMake(_scrollView.contentOffset.x, _scrollView.contentOffset.y);
    scrolledRect.size = backgroundImageView.frame.size;
    backgroundImageView.frame = scrolledRect;
}

こんな感じで実装する。scrollViewのdelegateを使って、bgImageViewのoriginを逐一変更する。
どこにでもあるコードだと思うけども、一応。


今度UIScrollViewのプロパティに関してまとめるかも?
いろいろ忘れるときがあるので。

UITableViewをアップデートする方法

UITableViewの表示を変更するときは、cellをリロードする必要がある。

それには2つの方法があるので簡単にまとめ。

1. [tableView reloadData]
     //Do some changes
     [tableView reloadData];

reloadDataメソッドは、cellをメソッドが呼ばれた時点で完全にリロードする。
そのため、アニメーションをかけたいときなどは使えない。

用途としては、別のコントローラーでデータを変更して、戻ってきたときに呼んでやると良い。


2. [tableView beginUpdate] ~ [tableView endUpdate]
     [tableView beginUpdate];
     //Do some changes
     [tableView endUpdate];

こちらの場合、beginUpdateからendUpdateの間に記述された処理を、UIVIewのアニメーションを使って実現される*1
その際、自分でanimationメソッドを呼ぶ必要がなく、内部で勝手に作ってくれる。



例えばこのような実装。
UICostomTableViewCellにてisOpenedプロパティを定義しておく。
cellがselectされたときに、!isOpenedだったら、cellの高さを2倍にする。そうでなければデフォルトの高さに戻す。

didSelectRowAtIndexPath:では、開かれたcellのindexPathをopenedCellPathsに格納しおき、heightForRowAtIndexPath:の内部で、格納されているindexPathに対応するcellの高さを2倍にして返している。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
    [tableView beginUpdates];     //Update 開始

    UICostomTableViewCell *cell = (UICostomTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
    if(!cell.isOpened)
    {
        //open
        cell.isOpened = YES;        

        //add indexPath
        [_openedCellPaths addObject:indexPath];
    }
    else
    {
        //close
        cell.isOpened = NO;    

        //remove indexPath
        for (NSIndexPath *path in [_openedCellPaths reverseObjectEnumerator])
        {
            if([path compare:indexPath] == NSOrderedSame)
            {
                NSUInteger removeIndex = [_openedCellPaths indexOfObject:path];
                [_openedCellPaths removeObjectAtIndex:removeIndex];
            }
        }
    }
    [tableView endUpdates];     //Update 終了
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat cellHeight = 0.0;
    CGFloat defaultCellHeight = 88;
    for (NSIndexPath *path in_openedCellPaths)
    {
        if([path compare:indexPath] == NSOrderedSame)
        {
            cellHeight = defaultCellHeight * 2;
            return cellHeight;
        }
    }
    cellHeight = defaultCellHeight;     
    return cellHeight;
}

UIViewのアニメーションを実装した訳ではないが、アニメーション付きで実行される。

*1:アニメーションの速度は0.3sです。

UIScreenのboundsとapplicationFrameの違い

StatusBarの有無で画面の使い方が微妙に変わり、毎回よく分からなくなるのでメモ。


    NSLog(@"bounds = %@",NSStringFromCGRect([UIScreen mainScreen].bounds));
    NSLog(@"applicationFrame = %@", NSStringFromCGRect([UIScreen mainScreen].applicationFrame));

出力がこちら

     bounds = {{0, 0}, {320, 480}}  
     applicationFrame = {{0, 20}, {320, 460}}

boundsは画面そのもののRectを、applicationFrameはStatusBarを取り除いた画面のRectを返す。

StatusBar 基準 原点 原点(boundsから見た時)
あり applicationFrame {0, 0} {0, 20}
なし bounds {0,0} {0, 0}


StatusBarを表示しておくと、そのすぐしたが、yの原点になる。
なので、画面上から20の位置がyの基準0となる。

FrozenBear v1.2.0

f:id:ryufloat:20130618200554j:plain
https://itunes.apple.com/jp/app/frozenbear-yinno-mingranaiaramu/id556500451?mt=8
先日FrozenBearの夏バージョンをリリースしました。

早速ですが、今回のアップデートでバグが見つかってしまいました。
稀に、設定画面で座標を変更すると落ちる事があります。
また同じタイミングで、画面がちかちかする等の挙動を確認しています。
現在、修正を試みていますので、申し訳ありませんが、しらばくお待ちいただければと。

また、そのようになった際、アプリケーションを一旦消去し、再度ダウンロードする事で正常な挙動に戻る事を確認していますので、もしも、上記のようなバグに遭遇してしまいましたら、再インストールをお願いいたします。


今回の主な変更点は以下になります。
・夏バージョンの追加
・通知センターからアラームをストップさせた際、アプリケーション側でもストップが押された状態で起動する
・色の微調整
・挙動の安定化
・その他細かい調整

CookPad Hackason 2013

CookPad Hackason 2013に鎖国のメンバーで参加しました。

今回はメンバーの一人が韓国で、一人が昼から深夜前まで居ないという状況でしたが、個人的には良い経験に成りました。
iOSに関してプログラムを書き始めて2年程度経ち、ある程度の事は出来ると考えていました。
が、そう甘くはないみたいです。

CoreData、UIImageのバイナリでの扱い、それらの連携、AssetLibrary。
新しく挑戦した事ばかりで、非常に手際が悪かったと、思い返して反省するばかりです。
未だにUIImageのバイナリの扱い方が分かっていません。DayOneを尊敬するばかりです。

そして紆余曲折あり、結局2つのアプリケーションの基礎を作成しました。
1つは完成には至りませんでしたが、2つ目の方をなんとか目を当てられる程度にする事は成功し、提出しました。

提出した物はこちら
http://sakoku-houjin.com/contrail/
実装は完璧ではないですが。

疲弊しましたが、とにかく楽しかったです。
自分の力の無さを実感出来ました。



以下ハッカソンのoverview

9時に3人が自宅に集合、テーマを見る。
考え始めるもまとまらず、作り始めるのは午後2時。
ハッカソン関係なく、良い物が出来そうだと思ったので、テーマに沿うってのは後付けにする事に決定。
初のCoreData挑戦。
UIImageをCoreDataで扱う事がうまくいかない(まだよくわかっていない)。
ライブラリの画像パスをデータに入れれば良いんじゃないか?(未実装)

なかなか進まない実装。
夜12時過ぎに、席を外していたメンバーが帰還。
やはり、もっとテーマに沿った物を作るべきじゃないのか?
作る作品を変更。現在午前2時。

無心でプログラムを書く。
9時になんとか(バグだらけだが)提出。



来年は、勝つ。