ios

A collection of 46 posts
Swift(iOSアプリ)でprintと debugPrintとNSLog
swift

Swift(iOSアプリ)でprintと debugPrintとNSLog

iOSアプリを作っているときログ出力をするならprint|debugPrint|NSLogいずれかを使うけど、Releaseビルドではどれが出力されるのか確認したことが無かったので確認をした。 Objective-CでiOSアプリを作っているときNSLogの出力はReleaseビルドでもログ出力されることは確認していたのでよくあるifdefマクロで LOG(...) のようにしていた。 実装 実装はXcodeでFile > New > Project... > AppでSwiftを使ったアプリ作成 ViewController.swiftの viewDidLoad() に下記を追記 print(">>> this is test message from print") print(">>> this is test message from debugPrint") NSLog(">>> this is test message from NSLog") ipaファイルの作成 あとは Archiveをして > Ad-Hoc ipaファイルを
2 min read
Unable to install "MyApp" 追記あり
xcode

Unable to install "MyApp" 追記あり

開発中のiOSアプリをXcodeから実機インストールしていたら Unable to install "MyApp" というエラーが発生するようになった。 MyAppはアプリ名 エラーのDetailsを確認すると This application’s application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed. 私の環境では、このエラーは再現したりしなかったり。 Xcodeでキャッシュの削除(Product > Clean Build Folder | ⇧⌘Kまたは⇧⌥⌘K)で再現しなくなったりまた再現したり、XcodeやmacOSの再起動などしても変わらず。再現性がわかりませんでした。 思い返すとこの開発中のアプリはEnterpriseアカウントでアプリの配布をしているので、以前にEnterprise配布ビルドのアプリをインストールして以来ずっ
2 min read
iOS13でアプリ名のローカライズがおかしくなる問題
xcode

iOS13でアプリ名のローカライズがおかしくなる問題

日本とと英語に対応したアプリを作成していて開発メンバー向けに配布したところ「iPhoneのホーム画面に表示されるアプリ名を正式版にして欲しい」と連絡が来た。 そのとき実際にはアプリ名を設定済みでSimulatorでも検証機のiPhone7(iOS12.4.1)でもアプリ名の表示を確認していた。 iPhoneのホーム画面に表示されるアプリ名のローカライズ 1. InfoPlist.string という Strings File を作成 XcodeProjectのLocalizations設定 デフォルトのEnglishに加えて、+ からJapaneseを追加。 このときローカライズ対応するファイルを指定しないと追加されないので、あらかじめ InfoPlist.string を作成しておく。 必要に応じて Use Base Internationalization をチェックするとBaseも追加される。 ローカライズに対応したファイルはXocde上では1つのファイルが折りたたまれたように表示されるが 実体は言語毎にディレクトリが作成されて内包されている
2 min read
ios

iOS13のFontFamilyName

* iOS8系でフォントの一覧 * iOS9系でフォントの一覧 * iOS10系でフォントの一覧 * iOS11系でフォントの一覧 * iOS12系でフォントの一覧 * iOS13系でフォントの一覧 取得方法 familyNameからfontNameを取得する。前回かより少し変更しました。 UIFont.familyNames .sorted { $0.compare($1) == .orderedAscending } .flatMap { UIFont.fontNames(forFamilyName: $0).sorted { $0.compare($1) == .orderedAscending } } .forEach { print($0) } 確認環境 iPhone 11 Pro Simulator (iOS13.3) 結果抜粋 AcademyEngravedLetPlain AlNile AlNile-Bold AmericanTypewriter AmericanTypewriter-Bold Am
2 min read
Xcode11 の Single View App をiOS12以前に対応させる
xcode

Xcode11 の Single View App をiOS12以前に対応させる

Xcode11で Single View App を Swift Storyboard の設定で作成して、iOS10系以降をサポートする設定にした。 ビルドすると沢山エラーが出た。 AppDelegate.swift と SceneDelegate.swift で、iOS13からavailableになったクラスが使用されているため。 赤丸が点いた箇所、画像の AppDelegate.swift ではfuncの宣言箇所で @available(iOS 13.0, *) を書く(赤丸をクリックすると自動で挿入してくれる)。 SceneDelegate.swift は class SceneDelegate 自体がiOS13以降のサポートとなるのでこうなる。 これでビルドに成功するようになる。 iOS12系の実機で実行するとコンソールに以下のメッセージが表示され、実機の画面は真っ暗になる。 2019-10-02 02:28:28.466280+0900 Demo[495:13067] [Application] The app del
2 min read
ios

iOS11とXcode9について思ったこと

Xcode9でのAdHocアプリのエクスポートまわりが色々と変わっていた。 Xcode ServerがXcodeに同梱されるようになった影響かもしれない。 https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html AdHocビルドするときに今まではTeamの選択をするだけだったけどプロビジョニングプロファイルも選択できるようになっていた。また成果物もAdHocビルドしたときに今まではipaファイルだけ書き出されてたけど * Packaging.log * ExportOptions.plist * DistributionSummary.plist というファイルたちも書き出されるようになった。これによって書き出したアプリのバンドルIDや使用したプロビジョニングファイルなども確認できるようになった。 これで本格的にCIを使った開発環境の構築が進めら
xcode8

Xcode8でBundle IDを設定する

Xcode8でBundle Identifier(以降Bundle ID)を設定する方法。 たしかXcode7あたりから設定箇所が変わりましたよね。 プロジェクトを作る Bundle IDはプロジェクトを作るときに設定する項目から自動的に作成されます。 = . Bundle IDを変更する ただ単にBundle IDを変更する場合の手順 1. Project Navigator(左ペインの一番左のアイコン) 2. プロジェクトの設定を開く 3. Bundle IDを変更したいTARGETを開く 4. Bundle Identifierを書き換える Bundle IDをConfigurationで分ける DebugビルドとReleaseビルドでBundle IDを分けたい場合。 1. Project Navigator(左ペインの一番左のアイコン) 2. プロジェクトの設定を開く 3. Bundle IDを変更したい
1 min read
ios

iOS開発初心者に知ってもらいたい開発スキル

この記事は画像がたくさんだったりしてすごく長いです。 SwiftでiOS開発の勉強をしている会社の新人と話をしているときに実装中のコードを見せてもらうと気になる実装があった。 let action = UIAlertAction(title: "title", style: .default, handler: { (action: UIAlertAction!) in ... }) UIAlertActionのイベントハンドラになるクロージャの引数の型が違う。 このイニシャライザのメソッド定義はこちら。 open class UIAlertAction : NSObject, NSCopying { public convenience init(title: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Swift.Void)? = nil) } handlerの引数クロージャの引数はUIAlertActionなのに、なぜかUIAlertAction!と書
6 min read
ios

iOSバージョンのシェアとアプリの対応OSバージョン@2016秋

iOSバージョンのシェアとアプリが対応するOSバージョンについて考える。 2016秋っていうのはざっくりとした期間にしたかっただけ。 Apple公式が出しているおおよその数値 2016年10月の時点でiOS8系とそれ以前のバージョンはAppStoreにアクセスしているうち8%ってことみたいですねー。だいぶ減りましたね。 私がかかわっているアプリではfabricをクラッシュレポートとしてとして使っていて、オマケ感覚でfabricのAnswersというDAUとか計測できるトラッキング機能を使用しているのですが。そのアプリだとiOS8系のユーザは3%弱でした。iOS8以降をサポートしているアプリなのでAppStoreとは分母も違うしってところですが、リテラシーが高い人向けというわけでもないアプリでiOS8系ユーザが3%弱ってことは、今後開発するアプリはもうiOS9以降サポートでいいよね!iOS8系は切り捨てちゃっていいよね! ここ数年で「古いOSもきっちりサポートしてよ」みたいな話は聞かなくなってきた気がします。 個人的にiOS8が切り捨てられて嬉しいこと 説
1 min read
xcode

iOS10.1 ATS

前回の検証がBeta版だったので安定版でも検証した 検証環境 * iPad Pro 9.7 * iOS10.1 * Xcode 8.1 * Swift3 検証方法 * 非SSLリクエスト先はhttp://www.example.com * SSLリクエスト先はhttps://www.example.com * 非SSLリクエストとSSLリクエストを行い結果を確認する(合計8つのリクエスト) * UIWebView * WKWebView * NSURLSessionで該当URLのソースコードをダウンロードして表示 * NSDataで該当URLのソースコードをダウンロードして表示 * これらのリクエスト結果がATSの設定パターンでどのように変わるのかを比較する 検証手順 * 上記検証方法に対応したプロジェクトを作成して実機起動(シミュレータは実機と異なる動作をすることが多いため) * http(s)リクエストのキャッシュが残らないよう都度アプリを再インストールする * 8リクエストが終わったら次の
1 min read
ios

iOS10ライフサイクル

先日Xcode8のフレームがどうのって記事を書いたんですけど、そんなことよりライフサイクルだな。と思ったのでシーケンス図風のものを書き出しました。png貼ってますがサイズ大きめです。参考程度に。上から下へ処理が進んで行きます(意味わかるよね? 今回使ったアプリ 確認した内容はこんな感じ + AppDelegate | | | + UINavigationController | | | +-+ UIViewController | | | +-+ UIView(UIViewController.view | + Notification * Storyboard使って、画面遷移などはしていないです * UITabBarControllerも使っていないです(ライフサイクルが結構かわるのですごく長くなるから 起動 その他バックグラウンド/フォアグラウンドなど その他 * バックグラウンドに移行する ≠ フォアグラウンドではなくなる(アプリが見えなくなる) * バックグラウンドに移行したかどうかは did
1 min read
xcode8

Xcode8 UIViewController.view.subviewsのframeについて(追記しました)

ビューのサイズが1000x1000になる Xcode8からStoryboardやxibでオブジェクトがframe値を持たなくなった影響で、UIViewController.view.subviewsのビューが正常なサイズを取得できなくて困るという話をよく耳にしている。 こんな感じのやつ > 自分もこれで困ることはあったけど、まぁ仕方ないからラクしないで修正しようか。くらいの気持ちでした。 検証した まずは通常のライフサイクルを確認する。 UIViewControllerとUIViewを拡張してログ出力するようにした。 // UIViewControllerのログ print("\(Date().description) : \(type(of: self)).\(#function):\(#line)") // UIViewのログ pri
7 min read
ios

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

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

UniversalLinksを実装した

仕事でUniversal Linksを実装することになったので検証環境を用意した。検証に使用したドメインは www.ikenie3.org 。Universal Links単体の実装というよりはHandoffとUniversal Linksの設定を同時に行っていく流れになりました。雑なので他の人が見ても意味がわからないかもしれないレベルのメモです。 作業内容 1. サーバ: https化 まず http://www.ikenie3.org をhttps化した。 が、必須ではなかったらしい。 URLがhttpsに対応している、もしくはUniversal Linksで使用するJSONファイルが署名されていることが条件ということでした。 証明書に関してはHandoffProgrammingGuideに指定の記載があります。 その際、iOSが信頼する認証局 (http://support.apple.com/kb/ht5012に列挙されている認証局)が発行した証明書とキーを、IDとして 指定します You can perform this tas
6 min read
ios

Swiftでアプリのバージョンチェック

アプリのバージョンチェックを実装するときは、特に何も考えず String.compare: メソッドを使えばいいじゃんと思っていたのですが、 String.compare: だけだと問題がありました。 結論 こんな感じで、 compare:options: で . NumericSearch を指定すればOKでした。 extension String { static func checkVersion(lhs lhs: String, rhs: String) { switch lhs.compare(rhs, options: .NumericSearch) { case .OrderedAscending: print("lhsの方がrhsよりも小さい") case .OrderedSame: print("lhsとrhsは等しい") case .OrderedDescending: print("lhsの方がrhsよりも大
1 min read
ios

iOSアプリのCrashログをsymbolicateする

iPhoneアプリのクラッシュログからクラッシュの原因を探す。 必要なもの 1. クラッシュログ 2. dSYMファイル クラッシュログを取得 クラッシュログ一覧を表示 Devicesウィンドウを開く Xcode Windows -> Devices (Shift+Cmd+2) 1. デバイスを選択 2. View Device Logs でクラッシュログの一覧を表示 クラッシュログのエクスポート 1. 該当アプリのクラッシュログをCtrl+左クリック(右クリック) 2. Export Log で任意のディレクトリに出力 dSYMファイルを取得 Organizerを開く Xcode Windows -> Organizer (Shift+Cmd+2) 該当アプリのクラッシュしたバイナリに対応するxcarchiveファイルを表示 1. 該当アプリを選択 2. クラッシュした時のビルドをCtrl+左クリック(右クリック) 3. Show
2 min read
ios

Xibファイルでレイアウトを定義したUIViewControllerで*LayoutGuideを使う

XIBファイルで開発を進めているけど UIViewController のサブビューが UINavigationBar にめり込んでつらいという話をされたので対策を考えた。 XIBファイルベースで開発するUIViewControllerサブクラスは FromNibViewController のサブクラスとして実装することを前提として。 class FromNibViewController: UIViewController { // MARK: -- Statics static var kTopLayoutConstraint: String { return "TopLayoutConstraint" } static var kBottomLayoutConstraint: String { return "BottomLayoutConstraint" } // MARK: -- Properties var topLayoutConstraint: NSLayoutConstraint! var
1 min read
xcode

Swiftのコンパイルはストレスが溜まるので

SwiftでiOSアプリを作成しているとコンパイル速度が遅くてストレス溜まるなーというタイミングが多々あるのでコンパイル速度というかストレスを減らそうという対応を幾つか記載。 やったこと プロジェクトのコンパイル時間計測オプションを設定する Xcodeプロジェクトの Bundle Settings にある Swift Compiler - Custom Flags で -Xfrontend -debug-time-function-bodies を設定する BuildTimeAnalyzer を入れる BuildTimeAnalyzer プラグインをインストールする 現行バージョンではBuildTimeAnalyzerの更新中にビルドし直すとクラッシュするけど重いメソッドが見られるので便利。 InterfaceBuilderの自動コンパイルを止める StoryboardかXibファイルを開いてInterfaceBuilderが表示されているときに Automatically Refresh Views のチェックを外す。 Xcod
3 min read
ios

Xcodeでコードを書かずに角丸のボタンを作る

タイトルの通り、プログラムらしいことをしないで角丸ボタンを表示する 手順 1. 角丸画像を用意する 2. XcodeのAssetに画像を追加する 3. 画像のスライス設定で可変領域を設定する 4. 角丸画像を表示したいボタンの背景画像(Background image)に設定する コードで実装する 覚えてたら後で書く その他 動画のアップロードがイケてない。youtubeとかじゃないとうまくいかないのかも。
ios

iOS8,9の違いを幾つか その1

次があるかわかりませんが、その1。 UIView Class 再描画でよく使われるメソッド - (void)layoutIfNeeded; 深度が違うようです。iOS9だと再帰的に適応されるようですが、iOS8だと深度が1か2か。 再描画されないなーということがありました。 気づいた時はframeの変更をしようとした時でした。 NSLocale Class - (NSArray*)preferredLanguages 出力する。 NSLog(@"%@", [NSLocale preferredLanguages]); iOS8系 ( ja, en, "zh-Hans", de ) この設定をしているiPhone(4S iOS8.3)のSS iOS9系 iOS9.0 実機で確認したところiOS8系と同じでした。 iOS9.1 ( "ja-JP", "en-JP", "de-JP", "zh-Hans-JP" )
1 min read
objc

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

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

iOSアプリのDBをCoredataからRealmへ

現時点の最新バージョン v0.96.2 での内容なので、バージョンによって違うかもしれないです。 GUIをインストール ブラウザが無いと閲覧できない。最新バージョンのzipをDL。 公式の日本語ドキュメントは最新バージョン用ではない可能性があるのでgithubのURLから直接落とす方が安心。 https://github.com/realm/realm-browser-osx/releases/ Xcode Plugin XcodeでModelファイルを新規作成するにはPluginを入れると簡単になるらしい。 Xcode Pluginは公式ドキュメントにならってAlcatrazからインストールする。 Xcode Pluginのインストールディレクトリパスはこちら ${HOME}/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins Alcatrazのインストール コマンドラインから実行 curl -fsSL https://raw.githubusercontent.c
3 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