2013年9月14日土曜日

iOS7対応: iOS6/7 delta



iOS7ではStatusBar、NavigationBarとアプリのViewがオーバラップして表示されるため、Xcode5のstoryboardで配置したViewの位置がiOS6/7で違ってしまう。

ViewのframeのルートViewに対するframe.origin.yの値が0の場合、iOS6ではStatusBar、NavigationBarの下に配置されるが、iOS7ではスクリーンの左上に配置される。

autolayoutの場合は調整してくれるようだが、そうでない場合は調整が必要になる。
Interface BuilderのサイズインスペクタにあるiOS6/7 deltaで行うことができる。

Xcode5ではこまめ表示/非表示ができるので、上のキャプチャーの少し上にあるViewのhideをクリックすると、この部分がすっかり隠れてしまいます。

iPhoneのUITableViewでは、iOS6と同じ設定だとiOS7ではViewの上にNavigationBar分の空きができる。この場合はiOS7の場合にcontentInsetのtopを-44にするとiOS6と同じレイアウトになる。

参考: Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?

2013年9月13日金曜日

iOS7対応: UIButtonの属性



UIButtonTypeRoundedRectのUIButtonをプログラムで作っている場合、iOS7では背景色なし、ボーダーなし、文字色シアンのため、iOS6から移行するとき調整が必要なことが多くなりそうです。

//背景色
myButton.backgroundColor = [UIColor lightGrayColor];

//文字色
//[myButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

//border
[[myButton layersetBorderWidth:1.0f];
[[myButton layer] setBorderColor:[UIColor darkGrayColor].CGColor];



iOS7対応: StatusBarが非表示にならない



iOS7: StatusBarが非表示にならない

//ルートのNavigationControllerに追加。
- (void)viewDidLoad
{
    [super viewDidAppear:animated];
    // iOS 7
    if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
        [self setNeedsStatusBarAppearanceUpdate];
    }
}

//StatusBarを非表示にしたいViewControllerに次のメソッドを追加する。
//defaultの値はNO
- (BOOL)prefersStatusBarHidden
{
    return YES;
}

NavigationControllerが複数ある場合は、各々で
[self setNeedsStatusBarAppearanceUpdate]
を呼ぶ必要があるかもしれません。

iPadでUISplitViewControllerを使う場合は振る舞いが異なる。
この場合。UISplitViewControllerにprefersStatusBarHiddenを実装、YESを返すようにすると全てのViewControllerでStatusBarが非表示になる。
個別にStatusBarの表示/非表示を切り替える方法は試していない。

2013年9月8日日曜日

UITextFieldのleftView追加例



UITextFieldの左側にundoボタンを追加する例です。
leftViewModeをUITextFieldViewModeWhileEditingとしたのでは表示されなかったので、becomeFirstResponder、resignFirstResponderをオーバライドし、表示/非表示を切り替えています。

//UITextFieldのサブクラスを作る。
@implementation MyTextFieldWithLeftView

//Storyboardで設定する場合の初期化
//leftViewにUIButtonをセット。
//初期状態は非表示。
- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(6,0,30,30);
        [btn setImage:[UIImage imageNamed:@"undo"]
                forState:UIControlStateNormal];
        self.leftView = btn;
    }
    return self;
}

//leftViewtarget/actionをセットする。
//複数のTextFieldがある場合、どれか区別がつくようにtagを設定する。
//部品が配置されるViewContollerなどから呼び、ボタンのtarget/actionをセットする。
- (void)addLeftButtonAction:(id)target action:(SEL)selector tag:(NSInteger)tag;
{
    [(id)self.leftView addTarget:target action:selector
                forControlEvents:UIControlEventTouchUpInside];
    self.leftView.tag = tag;
}

//firstResponderになるときにleftViewを表示。
- (BOOL)becomeFirstResponder
{
    self.leftViewMode = UITextFieldViewModeAlways;
    return [super becomeFirstResponder];
}

//firstResponderでなくなるときにleftViewを非表示。
- (BOOL)resignFirstResponder
{
    self.leftViewMode = UITextFieldViewModeNever;
    return [super resignFirstResponder];
}

2013年9月4日水曜日

Archive作成時の header file not found エラー



アプリとstatic libraryのProjectがあるworkspaceで、Archive作成時にヘッダファイルが見つからないエラーが発生しました。
エラーメッセージは次のようなものです。
Lexical or Processor Issue
/Users/.../AppWorkspace/LibA/LibA/MyClassA.h:10:9:
  'LibB/MyClassB.h' file not found

いろいろバリエーションがあるようですが、基本的にはヘッダのサーチパスの設定に由来するようです。
私の場合はworkspaceにアプリのプロジェクトとstatic libraryがふたつあり、そのひとつが他方に依存しているという環境で発生しました。
App - libA、libBに依存
libA - libBに依存
libB

この場合、libAのビルドに失敗しているので、libAのBuild Settingsに設定を追加します。
Build Settings > Serach Paths > User Search Paths > Release
"$(PROJECT_DIR)/.."  recursive

recurciveの設定は入力フィールドをダブルクリックすると表示されるダイアログの右端にある、non-recursive/recursive切り替えスイッチで行います。

次のサイトを参考にしましたが、私の場合はUser Search Pathsの追加だけで解決しています。これだけではダメな場合は参照してみてください。

http://stackoverflow.com/questions/5413338/xcode-4-and-nested-projects-header-files-not-found

http://stackoverflow.com/questions/5584317/compile-build-or-archive-problems-with-xcode-4-and-dependencies