Showing posts with label Objective-C. Show all posts
Showing posts with label Objective-C. Show all posts

Thursday, October 10, 2013

deprecated sizeWithFont

presentVC iOS7対応

UITextView iOS7対応

Sunday, April 7, 2013

Unused VariableのWarningを無視

__unused を頭につける
__unused NSInteger i;

よほど変なことしない限り必要なさそうですけど


参考

nested push animation can result in corrupted navigation bar

storyboardでUITableViewからpushするUIViewControllerへsegueを繋げて、
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 [self performSegueWithIdentifier:@"TestView" sender:nil];
}
で、pushした場合に、下のエラーが出た
2013-04-07 23:35:39.020 TestApp[24121:907] nested push animation can result in corrupted navigation bar
2013-04-07 23:35:39.395 TestApp[24121:907] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2013-04-07 23:35:39.399 TestApp[24121:907] Unbalanced calls to begin/end appearance transitions for .
push、popの動作もおかしくなってしまう模様

原因としては、UITableViewCellのSelection Segue(push)からUIViewControllerに繋げてしまっていたので、
UITableViewのManual Segue(push)から繋げるようにして解決
Cellから繋げる場合は明示的に、performSegueWithIdentifier: しなくていいのね


参考

Wednesday, March 20, 2013

warning: Attribute Unavailable: Freeform Size simulated metrics are not available prior to Xcode 4.2.

NIBの設定を変える。
[Interface Builder Document]→[Development]を変える。


参考

Xcode4.6スタティックライブラリ

ライブラリ

Cocoa Touch Static Libraryでプロジェクトを作成
Build Settingsで
・Skip Install→YES
・Other Linker Flags→-ObjC
Build Phasesで
・Copy Filesに.hファイルを追加

使う側のプロジェクト

ライブラリの.xcodeprojをプロジェクトに入れるか同じワークスペースに入れる
Linked Frameworks and Librariesにライブラリの.aを追加
Build Settingsで
・Other Linker Flags→-ObjC
・Always Search User Paths→YES
・Header Search Path→$(BUILT_PRODUCTS_DIR)
・User Header Search Paths→ライブラリの絶対パスを指定

Tuesday, March 19, 2013

navigationBarとtoolBarを透明にする

navigationbar, toolbarをUIBarStyleBlackTranslucent以外で透明にする方法

barのbackgroundimageに透明なimageを設定
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor colorWithWhite:0.0f alpha:0.8f]] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.toolBar setBackgroundImage:[UIImage imageWithColor:[UIColor colorWithWhite:0.0f alpha:0.8f]] forToolbarPosition:UIToolbarPositionBottom barMetrics:UIBarMetricsDefault];

透明なimageはどう生成してもいいんですが、ここでは以下のカテゴリで作成している
#import "UIImage+Color.h"

@implementation UIImage (Color)

+ (UIImage *)imageWithColor:(UIColor *)color
{
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
        
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
        
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
        
    return image;
}

@end

Friday, March 15, 2013

UIScrollViewでnavigationBarやtoolBarをスクロール範囲に被らないように透けさせて配置

タイトルが長い

どういうことかと言うと、普通にnavigationBarとtoolBarをUIBarStyleBlackTranslucentに設定して、
UIScrollViewをself.viewに突っ込むだけだと、
スクロール範囲がnavigationBarとtoolBarに被ってしまって見栄えが非常に良くない
(例えば一番下までスクロールしても、UIScrollViewのcontentがtoolBarに被ってしまう)

これが例えば、UITableViewContollerを使ったりすると、
tableViewは透けるのにスクロール範囲はnavigationBar, toolBarに被らないように
よろしくやってくれたりする

それをUIScrollViewでやりたい
上記を実現する為に、
  1. UIScrollViewのcontentの余白をbarのheight分縮める
  2. UIScrollViewのスクロールバーの余白?もbarのheight分縮める
コードで書くと、以下のような感じ

// 対象のscrollView
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
                 :
- (void)viewDidLoad
{
 [super viewDidLoad];

 // barを透明に
 self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
 self.navigationController.toolbar.barStyle = UIBarStyleBlackTranslucent;

 UIEdgeInsets insets;
 // contentを縮める
 insets= self.scrollView.contentInset;
 insets.top = self.navigationController.navigationBar.frame.size.height;
 insets.bottom = self.navigationController.toolbar.frame.size.height;
 self.scrollView.contentInset = insets;
 // スクロールバーの範囲を縮める
 insets = self.scrollView.scrollIndicatorInsets;
 insets.top = self.navigationController.navigationBar.frame.size.height;
 insets.bottom = self.navigationController.toolbar.frame.size.height;
 self.scrollView.scrollIndicatorInsets = insets;
 
 // そのままだと初期位置がnavigationBarに被るので下にずらす
 CGPoint point = self.scrollView.contentOffset;
 point.y = -1*self.scrollView.contentInset.top;
 self.scrollView.contentOffset = point;
}

これでいろいろ透けさせることができそう(意味深)


参考

Friday, February 22, 2013

NSOperationのプロパティ

NSOperationのサブクラスを作って、
そのクラスに
@property (nonatomic, copy) DummyBlock completionBlock;
という名前のプロパティを作成して、
Operation完了後の処理をこのBlocksで実行するように実装すると、
いろいろ挙動がおかしくなります
(setCompletionBlockというメソッドがNSOperationの抽象メソッドのため)

名前を変えたら期待通りの動きになった
Xcodeだとオーバーライドしてるのがわかりにくいなと思った

Sunday, February 17, 2013

Xcode4.6でiOS framework作成

iOSのframework作成をしようと、いろいろ参考にしたけど、すごく詰まったので一応書いておく
Xcodeのバージョンは4.6

Project作成

[File]→[New]→[Project]
を選択
[iOS]→[Framework & Library]→[Cocoa Touch Static Library]

[Product Name] "MyLibrary" と入力(名前を決める。***.framework の *** の部分)
[Organization Name] と [Company Identifier] は適当に
[Include Unit Tests] はどちらでも
[Use Automatic Reference Counting] はチェック入れたままで

パスはまあ適当に好きな所に作成


Headerディレクトリ作成

Xcode の MyLibrary ディレクトリを右クリックして[Add Files to "MyLibrary"...]をクリック
出てきたプロンプトの左下の[New Folder]をクリックして "Headers" と入力して[Create]
右下の[Add]でプロジェクトに追加
ここに公開したい .hファイルを置く(ライブラリを実装したら入れてください)


ターゲット作成

[TARGETS]→[MyLibrary]を選択して、左下の[Add Target]をクリック
[iOS]→[Other]→[Aggregate]

[Product Name] "MyLibrary-Universal" と入力(何でもいい?)
[Finish]して作成


スキーマ設定変更

[Manage schemes]で MyLibrary の Show のチェックを外す
(別に外す必要はないけど、使用しないので非表示にしているだけ)


Info.plist作成

[Supporting Files]を右クリックして[New File...]をクリック
[iOS]→[Resource]→[Property List]

[Save As:]に "Info.plist" と入力
[Create]して作成
Info.plist を右クリックして[Open As]→[Source Code]
下のコードをコピーして上書き。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>CFBundleName</key>
 <string>MyLibrary</string>
 <key>CFBundleIdentifier</key>
 <string>com.blogspot.fiahfy.MyLibrary</string>
 <key>CFBundleInfoDictionaryVersion</key>
 <string>6.0</string>
 <key>CFBundleVersion</key>
 <string>1</string>
 <key>CFBundleExecutable</key>
 <string>MyLibrary</string>
 <key>CFBundleGetInfoString</key>
 <string>MyLibrary</string>
 <key>NSPrincipalClass</key>
 <string></string>
 <key>CFBundlePackageType</key>
 <string>FMWK</string>
 <key>CFBundleIconFile</key>
 <string></string>
 <key>CFBundleSignature</key>
 <string>????</string>
 <key>CFBundleDevelopmentRegion</key>
 <string>English</string>
 <key>NSHumanReadableCopyright</key>
 <string>Copyright fiahfy. All rights reserved.</string>
 <key>CFBundleShortVersionString</key>
 <string>1.0.0</string>
</dict>
</plist>

Info.plist を右クリックして[Open As]→[Property List]
で開き直して、
MyLibrary, com.blogspot.fiahfy.MyLibrary, fiahfy
等の部分を自分で設定したものに適宜変更する


スクリプト設定

[TARGETS]→[MyLibrary-Universal]を選択して、
[Build Phases]→[Add Build Phase]→[Add Run Script]をクリック
"Type a script or drag a script file from your workspace" の部分に以下のスクリプトをコピペ
# Environment Variables
INFO_PLIST="Info.plist"
FRAMEWORK_NAME=${PROJECT_NAME}
FRAMEWORK_VERSION_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" ${SRCROOT}/${PROJECT_NAME}/${INFO_PLIST})
FRAMEWORK_VERSION=A
FRAMEWORK_BUILD_PATH="${SRCROOT}/build/${CONFIGURATION}-framework"
FRAMEWORK_DIR="${FRAMEWORK_BUILD_PATH}/${FRAMEWORK_NAME}.framework"
FRAMEWORK_PACKAGE_NAME="${FRAMEWORK_NAME}.${FRAMEWORK_VERSION_NUMBER}.zip"

# Clean directories
[ -d "${FRAMEWORK_BUILD_PATH}" ] && rm -rf "${FRAMEWORK_BUILD_PATH}"

# Build simulator and device binaries.
xcodebuild -project ${PROJECT_NAME}.xcodeproj \
 -sdk iphonesimulator${IPHONEOS_DEPLOYMENT_TARGET} \
 -target "${PROJECT_NAME}" \
 -configuration ${CONFIGURATION} clean build
xcodebuild -project ${PROJECT_NAME}.xcodeproj \
 -sdk iphoneos${IPHONEOS_DEPLOYMENT_TARGET} \
 -target "${PROJECT_NAME}" \
 -configuration ${CONFIGURATION} clean build

# create framework directories.
mkdir -p ${FRAMEWORK_DIR}
mkdir -p ${FRAMEWORK_DIR}/Versions
mkdir -p ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION}
mkdir -p ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION}/Resources
mkdir -p ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION}/Headers

# create symlinks
ln -s ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION} ${FRAMEWORK_DIR}/Versions/Current
ln -s ${FRAMEWORK_DIR}/Versions/Current/Headers ${FRAMEWORK_DIR}/Headers
ln -s ${FRAMEWORK_DIR}/Versions/Current/Resources ${FRAMEWORK_DIR}/Resources
ln -s ${FRAMEWORK_DIR}/Versions/Current/${FRAMEWORK_NAME} ${FRAMEWORK_DIR}/${FRAMEWORK_NAME}

# create the universal library
lipo -create \
 ${SRCROOT}/build/${CONFIGURATION}-iphoneos/lib${FRAMEWORK_NAME}.a \
 ${SRCROOT}/build/${CONFIGURATION}-iphonesimulator/lib${FRAMEWORK_NAME}.a \
 -output "${FRAMEWORK_DIR}/Versions/Current/${FRAMEWORK_NAME}"

# copy files
ls ${SRCROOT}/${PROJECT_NAME}/Headers/*.h > /dev/null 2>&1 && cp ${SRCROOT}/${PROJECT_NAME}/Headers/*.h ${FRAMEWORK_DIR}/Headers/
cp ${SRCROOT}/${PROJECT_NAME}/${INFO_PLIST} ${FRAMEWORK_DIR}/Resources

# create zip
cd ${FRAMEWORK_BUILD_PATH}
zip -ry ${FRAMEWORK_PACKAGE_NAME} $(basename $FRAMEWORK_DIR)



ここまで設定すればビルドは一応通るはず(中身がないので意味のないframeworkですが)

ビルド後は
build/Debug-framework/MyLibrary.framework
が作成されているので、これを使用したいプロジェクトで「Linked Frameworks and Libraries」に追加すればおk

リリースビルドした場合は
build/Release-framework/MyLibrary.framework
で、配布したい時は
build/Release-framework/MyLibrary.1.0.0.zip
を配ればよいって感じかと思います

中身書く前に疲れたっていう


参考

Tuesday, February 12, 2013

blocksで遅延実行

blocksで遅延実行
// 2秒遅延
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
// code
});

Objective-Cのリテラル表現

Objective-Cのリテラル表現(Xcode4.4以降)
// Array
NSArray *array = @[@"hoge", @"fuga"];
// Dictionary
NSDictionary *dictionary = @{@"key1" : @"val2", @"key2" : @"val2"};
// Number
NSNumber *number1 = @100;
NSNumber *number2 = @YES;

// 添字アクセス
NSString *str1 = array[0];     // @"hoge"
NSString *str2 = dictionary[@"key2"];      // @"val2"

コードが大分すっきりするようになっていいです


参考

Objective-Cデバッグ用にエラー出力

デバッグ用に以下を入れる

@AppDelegate.m
void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Override point for customization after application launch.
    return YES;
}
なんかいろいろ出てきて便利


参考

Sunday, February 10, 2013

iphoneアプリのiconとsplash

アイコンサイズやら起動画面の画像サイズとか

splash
Default.png320x480 px
Default@2x.png640x960 px
Default-568h@2x.png640x1136 px
Default-Portrait~ipad.png768x1004 px
Default-Portrait@2x~ipad.png1586x2008 px
Default-Landscape~ipad.png1024x748 px
Default-Landscape@2x~ipad.png2048x1496 px

icon
Icon.png57x57 px
Icon@2x.png114x114 px
Icon-72.png72x72 px
Icon-72@2x.png144x144 px
Icon-small.png29x29 px
Icon-small@2x.png58x58 px
Icon-small-50.png50x50 px
Icon-small-50@2x.png100x100 px

とりあえず以上のサイズを作成


参考

Multiple build commands for output file

xcodeで何度かIconを再登録していたらなんか上記のwarningが出た

[TARGETS]→[Build phases]→[Copy Bundle Resources]
で重複しているファイルを削除で解消


参考

SyntaxHighlighterでObjective-C

SyntaxHighlighterでObjective-Cをハイライトできなかったので以下のJSをヘッダに追加
<script src='https://raw.github.com/andrashatvani/shBrushObjC/master/shBrushObjC.js' type='text/javascript'/>
あとはエイリアスをocに設定
<pre class="brush: oc;">
    NSLog(@"hoge");
</pre>

参考

キーボード表示時にリサイズ

キーボード表示時にUITextViewをリサイズするテンプレ

Landscapeの場合keyboardRectのwidthとheightが逆になるので考慮する
self.viewのサイズを取得する場合はboundsを使用する。(frameの場合Landscapeになっても値が変わらない)

- (void)viewWillAppear:(BOOL)animated
{
 [super viewWillAppear:animated];
 
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewDidDisappear:(BOOL)animated
{
 [super viewDidDisappear:animated];
 
 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

:

- (void)keyboardWillShow:(NSNotification*)notification
{
 CGRect keyboardRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
 if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
  CGRect rect = keyboardRect;
  rect.size.width = keyboardRect.size.height;
  rect.size.height = keyboardRect.size.width;
  keyboardRect = rect;
 }
 CGRect frame = self.textView.frame;
 frame.size.height = self.view.bounds.size.height - keyboardRect.size.height;
  
 NSTimeInterval duration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
 
 UIViewAnimationCurve curve = [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
 
 [UIView animateWithDuration:duration delay:0.0f options:(curve << 16) animations:^{
  self.textView.frame = frame;
 } completion:nil];
}

- (void)keyboardWillHide:(NSNotification*)notification
{
 CGRect frame = self.textView.frame;
 frame.size.height = self.view.bounds.size.height;
 
 NSTimeInterval duration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
 
 UIViewAnimationCurve curve = [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
 
 [UIView animateWithDuration:duration delay:0.0f options:(curve << 16) animations:^{
  self.textView.frame = frame;
 } completion:nil];
}