objc

A collection of 20 posts
ObjCのXcodeプロジェクトをSwiftのプロジェクトに変更する
xcode

ObjCのXcodeプロジェクトをSwiftのプロジェクトに変更する

Objective-Cで作成されているプロジェクトをSwift混在プロジェクトに作り替えようという話があった。 XcodeのテンプレートプロジェクトではObjective-CとSwiftどちらの言語を選べるけど、言語が変わる以上に何が変わるのかというかどこが言語選択のキモになるかを調べたので需要は無いだろうけど、Objective-CベースのプロジェクトをSwiftベースのプロジェクトに作り替えた作業のログを書く。 日本語がおかしかったので編集したらもっと日本語がおかしくなった。 なんでSwift混在にしたいのか 最近は主にSwiftで開発を行っていて、サードパーティーのライブラリもSwiftのものを利用しているから。 Objective-C製のライブラリをSwiftで使うときは割とどうとでもなるけど、Swift製のライブラリをObjective-Cで使うときはライブラリが内部クラスなのか public なクラスなのか設定が必要とかそういうのがあったはず。 そのため新規開発する部分はSwiftで、外部ライブラリを使用したいObjective-Cの実装もSwiftでex
2 min read
ios10

iOS10のFontFamilyName

旧OS * iOS8系でフォントの一覧 * iOS9系でフォントの一覧 * iOS10系でフォントの一覧 * iOS11系でフォントの一覧 * iOS12系でフォントの一覧 * iOS13系でフォントの一覧 iOS10でフォント一覧を書き出すの忘れていた。 Swift3での取得方法が気に入らなかったので修正。ObjCとそーとのロジックが異なるけどもう不要かなって気もする。 取得方法 familyNameからfontNameを取得する。今回からソートするようにした。 //////////// // Objc NSMutableArray<NSString*> *array = [NSMutableArray array]; for (NSString *familyName in [UIFont familyNames]) { for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) { [array addObject:fontName];
2 min read
objc

Date型の比較@ObjC/Swift

Date型の比較をするとき、多くの場合は"2016-12-09"とか"2016-12-09 10:00:00+0900"とか、年月日か年月日と時分秒までの比較が多いのかなと思いますが。 Objective-C -[NSDate earlierDate:]と-[NSDate laterDate:]が使えるので、挙動を理解していればそれがラクかなと思いますが、可読性を考えると[NSDate compare:]で比較した方がわかりやすいときもあるかもしれない。 -[NSDate earlierDate:]と-[NSDate laterDate:]は自身とanotherDateの値が等しい場合には自身の値を返すことだけ覚えておく必要がある。(なのでログ出力ではポインタを吐いている NSDateFormatter *df = [[NSDateFormatter alloc] init]; df.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"
1 min read
ios

UICollectionViewで横スクロールページングのインデックス取得

UICollectionViewでシンプルなページングする横スクロール画面を実装した時に、何番目のセルを表示中か取得しようとしたらうまくいかない状況があったのでほぼメモ。 // Before - (NSInteger)visibleIndex { NSInteger index = NSNotFound; NSArray<NSIndexPath *> *indexPaths = [self.collectionView indexPathsForVisibleItems]; NSIndexPath *indexPath = [indexPaths firstObject]; if (indexPath) { index = indexPath.row; } return index; } // After - (NSInteger)visibleIndex { NSInteger index = NSNotFound; NSArray<NSIndexPath *> *indexPaths = [sel
1 min read
objc

[Objective-C] 特定の緯度経度と角度と距離を元に緯度経度を算出する(楕円あり)

現在地を起点として、特定距離の矩形を作成する。 みたいなことが必要だったので計算式を書いた(ほぼコピペ)。。。けど使われないことになった。 やってることとしては ある地点を中心とした半径Xメートル同心円上における角度Aの地点の緯度経度を求めよ(ただし地球は楕円形として扱うこと) みたいな感じでしょうか。文系な自分にはこういうのよくわからないです。。 結果として下記ソースでほぼイケるけど、浮動小数点数の演算ばかりなので誤差が気になるところ。メソッドのコメントに記載しているURLでJavascriptのソースがあったので、Objective-Cに書き直しただけって感じですが、一部変えています。詳細はソース見てもらえれば。 参考サイトではdo whileでループしているが この部分の動作を見てみたら、Javascriptでは精度を上げるようなループをしていたけど期待通りに実装する方法がわからなかったので、ループの中身を1度実行するだけに変更しています。 #import <CoreLocation/CoreLocation.h> #define
2 min read
xcode7

xcode7でNullabilityを定義 したヘッダにblocksをtypedef定義したらエラーが出た

typedef (^ SimpleBlock) (id obj); とかをconfig的な場所で定義して、いろんな場所で使っていた。 たまたまヘッダーファイルをがっつりいじる機会があったので、nonnullとかnullableとかも書いて、ヘッダの上の方で定義していたので存在を忘れていた。 そのままコンパイルしたらワーニングが出ていた。 pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) あ、すみません。と思ってnullableと書いてコンパイルしたらエラー。 unknown type name 'nullable' expected ')' こんな感じでいくつか。 結論は最初のワーニングに書いてあって、この通りに書けばよかった。 1. _Nonnull 2. _Nullable 3. _Null_unspecified つまりこんな。 typedef (^ SimpleBlock) (_Nulla
ios

iOS7,8,9のアプリケーションライフサイクル

以前に作ったアプリがiOS9でうまく動かないという連絡を受けたので調査した結果、アプリケーションのライフサイクルが変更されたことによりイベントトリガと描画の関係が前後するというしょぼいミスをしていました。 悔しいので変化をまとめました。 具体的な問題の原因となった箇所はこちら。詳細は下のライフサイクルを見たらわかります。 -[AppDelegate applicationDidBecomeActive:] 検証したアプリの画面構成 1. UINavigationController 2. FirstViewController 3. SecondViewController(FirstViewController.navigationControllerにpushされる) iOS7 (7.1.2 // 起動 -[FirstViewController awakeFromNib] -[AppDelegate application:willFinishLaunchingWithOptions:] -[AppDelegate application:d
1 min read
xcode

Xcode7からのBundle Identifier定義

--- 追記@2016/12/6 こっちにXcode8での設定方法を書きました --- 追記ここまで Xcode6系まではinfo.plistで直接定義する形だったけど Xcode7からはProjectファイルで定義するようになって、info.plistのbundle identifierの項目はこんな感じになっていた(Xcodeのマイグレーションをするとこうなるということで。 $(PRODUCT_BUNDLE_IDENTIFIER) メリット ビルド設定(Build Configuration)でバンドルIDが変更できるようになった。 Debugビルド、Releaseビルド、AdHocビルドなどでバンドルIDが変更できるのでターゲットを無駄に追加する必要が無くなった。 デメリット 理解していない人がinfo.plistを書き換えたら死ねる。 下手に書き換えられたら別アプリになるから。。。
ios

iOS9のFontFamilyName

iOS8系でフォントの一覧を出したので、iOS9でもやっておく。 なんかfamilyNamesの中身が無いものもいくつかあったぽい(たぶんCJKとか言語に依存するものだと思う)。 取得方法 familyNameからfontNameを取得する。 for (NSString *familyName in [UIFont familyNames]) { for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) { NSLog(@"%@", fontName); } } 確認環境 iPhone Simulator (iOS9) 結果抜粋 Copperplate-Light Copperplate Copperplate-Bold IowanOldStyle-Italic IowanOldStyle-Roman IowanOldStyle-BoldItalic IowanOldStyle-Bold KohinoorTelugu-Regular
2 min read
objc

iOS8のFontFamilyName

iOS9はこちら 取得方法 familyNameからfontNameを取得する。 for (NSString *familyName in [UIFont familyNames]) { for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) { NSLog(@"%@", fontName); } } 確認環境 iPhone Simulator (iOS8.2) 結果抜粋 Marion-Italic Marion-Bold Marion-Regular Copperplate-Light Copperplate Copperplate-Bold STHeitiSC-Medium STHeitiSC-Light IowanOldStyle-Italic IowanOldStyle-Roman IowanOldStyle-BoldItalic IowanOldStyle-Bold CourierNewPS-BoldMT CourierNe
2 min read
objc

IBInspectableを使ったらエラーが出た

IBInspectableを使うとInterfacebuilderがよしなに表示を変えてくれるとかいうのは知ってた(試しに使ったことはあった程度だった)けど、IBInspectableを使っているライブラリがあったので使ってみた。 IB Designables Failed to render instance of XXX: Rendering the view took longer than 200ms. Your drawing code may suffer from slow... こんな感じのエラーが出た。xibファイルが無駄に複雑で巨大なせいでレンダリングが遅い画面だったけど、IBInspectableを使った結果余計なエラーが出るようになった。 もちろんビルドには問題ない。ただ気持ち悪いだけで。
objc

NSLayoutConstraint.constantの値を変更してビューのサイズを取得した

フラグでNSLayoutConstraint.constantの値を変更してscrollViewのcontentSizeを変更する、ということをしようとしたけどうまくいかなかった。 CGRectGetMaxY()の時点では_childView.frameにはconstraintの値が反映されてなかった。 だいたいの処理の流れ(適当) - (void)updateConstraint { if ([self isHidden]) { _childViewConstraint.constant = 100.f; } else { _childViewConstraint.constant = 0.f; } CGRect frame = _mainView.frame; frame.size.height = CGRectGetMaxY(_childViewConstraint.frame); _mainView.frame = frame; CGSize cont
objc

NSURLSessionでBasic認証する

どうせ1つのアプリで複数のBasic認証することなんて無いっしょ とか思いつつも使い回しがききそうな実装を考えたのでメモ 1. requestのURLはhttp://user:password@example.comみたいにユーザとパスワードも記載しておくとする 2. NSURLSessionTaskのcompletionHandlerは使わないでdelegateを使用する 3. WWW-Authenticateのrealmを取得 4. 認証するURLに対してcurl -vとかリクエストして401レスポンスを取得 5. 今回はこんなレスポンスが来ていたWWW-Authenticate: Basic realm="Login Required" 6. 該当realmはLogin Required 7. delegateメソッド- URLSession:didReceiveChallenge:completionHandler:を実装する 8. - URLSession:didReceiveChallenge:completionHandler: - (void)
1 min read
objc

Xcode6.1.1で実機が選択できなかった

先日買ったiPadに開発中のアプリをインストールしようとしたらデバイス一覧に表示されず2日間ほど無駄をしてしまった。 プロジェクトのバンドルIDもプロビジョニングも問題無いことは確認済みだった(別Macではインストールできた)ので、MacかXcodeの設定に問題があるのだろうと思っていた。 解決方法 * 実機をMacに接続 * ステータスバーのWindow > Devices * Devicesウィンドウの左上DEVICESで該当の実機を[Ctrl+Click] * Show in Run Destinations Menuをクリック(チェックがついたらOK) 参考 Stack Overflow
objc

UIWebView Cache Clear

UIWebViewのキャッシュクリアが地味に面倒だったのでログ iOS7系のキャッシュクリアがなんか変だった。詳しく調査してないけどこれでうまくうごいた。 やること1 UIAppcalation method - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions とか絶対呼ばれる場所に下を書いておく // WebViewのキャッシュを削除 [NSURLCache sharedURLCache].memoryCapacity = 0; [NSURLCache sharedURLCache].diskCapacity = 0; やること2 UIWebViewDelegate method - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationTyp
objc

iOS8でプッシュ通知を使ったりバッジを使ったり

今までプッシュ通知の利用を宣言するのに使ってたメソッドregisterForRemoteNotificationTypesがiOS8からdeprecatedに変わっていたのでメモ プッシュ通知の利用するとき iOS7以前の場合 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; iOS8以降の場合 [[UIApplication sharedApplication] registerForRemoteNotifications]; UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNot
2 min read
objc

iOS用にユニバーサルライブラリを作る

BlocksKitをフレームワーク化した iOS8対応のためBlocksKitをフレームワーク化したログ。 ソースコードのまま組み込むとかイヤなのでよく外部のライブラリはフレームワークにしているのでメモ。 手順 ダウンロードからビルドまで * github から最新ソースコードをダウンロード * ターゲットをBlocksKitにしてiOS Device用Releaseビルド * ターゲットをBlocksKitのままiPhone Simulator用Releaseビルド * OrganizerでBlocksKitのDerived Dataディレクトリ右の->をクリックしてFinderに表示 以下コマンドライン ターミナルのログからひっぱり出したコマンドなので間違ってる可能性は否定できない。 $ cd <Derived Data Dir> // FinderからD&Dでpathが貼り付けできるのでそれがらく) $ xcrun lipo -info ./Release-iphoneos/libBlocksKit.a Architectures in
1 min read