カテゴリー別アーカイブ: iOS

【iOSメモ】iOS9でUnwindSegueが動作しない

iOS8では問題なかったUnwindSegueが、iOS9へアップデートしたデバイス上では動作しなくなった。

参考リンク先によると、Custom UnwindSegueを使用するためにCustom Container ViewController(UINavigationControllerのサブクラス)でオーバーライドしている以下のメソッドが問題らしい。

ただし、このメソッドはiOS9からDeprecatedされてる。

そして新たに登場するのが、

なぜかこのメソッドは現時点ではドキュメントに記載されていない。

詳細は参考リンク先に任せるが、iOS8以前とiOS9以降両方の環境に対応するためには、これらのメソッドを混在させないといけない。
結局リンク先の記事を参考にいろいろ弄ってみて落ち着いたのが以下のコード。

とにかくiOS9では、unwindForSegue:towardsViewController: を呼んでやることが重要らしい。

だがいろいろ試してる途中で、pushとmodalで動作が異なっていたり、headerコメント通りの結果にならなかったり、怪しい動作がちらほらと。

そもそもDeprecatedされたメソッド使ってるので、将来のOSバージョンアップで動作かわる可能性はあるので、気に留めておかないといけない。

面倒くさい。

参考

Custom Unwind Segue for iOS 8 and iOS 9

 

 


【iOSメモ】SLServiceTypeFacebookの場合、SLComposeViewControllerのsetInitialTextメソッドが機能しない

2015/5/29追記

Facebook Developers サイトのBugsレポートで見かけた。
SLComposeViewController no longer works after Apr 24th Facebook App update

Facebookの中の人の最後のコメントが、

Amudi Sebastian ·  · Facebook Team

setInitialText behavior is by design. Please refer to the Platform Policy here: https://developers.facebook.com/docs/apps/review/prefill
May 26 at 12:26pm · Edited · Confidential Reply · Reply
 
このレポートのstatusはFixedになってるので現時点でこれが答えですな。。。
 
 

setInitialTextしても初期テキストが表示されない

ふと気づくと、setInitialTextメソッドを使って初期テキストを設定しても、SLComposeViewControllerの画面に初期テキストが表示されなくなっていた。

 

調べてみると、Facebookへのシェア時には、投稿文はすべてユーザーが自分で書いたものしか許されない、というFacebook側のプラットフォームポリシーが原因のようす。

新しく追加されたポリシーなのか、以前からあったものが厳格に適用されるようになったのかは不明。。

内容を読むと、ユーザーが自分で編集したり削除したりできるものであってもNG、ユーザーがボタンをタップして自動入力させるようなものであってもNG、など個人的にはちょっと厳しすぎるんじゃないかと思える内容となっている。

iOSはこれに準じて動作しているようで、今のところ回避策は見えない。
iOS8.3から症状が出たと書いてるサイトもあったけど、手元ではiOS8.0.2でも再現してるのでたぶんiOSバージョンは関係ない。

ちなみに、Facebookアプリを削除すると現象は治ってInitialTextが表示されるようになる。
なんの解決にもならないけど。。

 

参考リンク

Sharing on iOS

Platform Policy 2.3 Example and Explanation


【iOSメモ】画像の撮影日時を特定したい

画像の撮影日時を特定したい

画像データの撮影日時を特定しようとして、Exif撮影日時の取り扱いにちょっと悩んだ。
理解不足があるかもしれないけど、現時点で分かったことをメモしておく。

 

そもそもの要件として

  • UIImagePickerControllerのカメラまたはフォトライブラリから画像を取得する。
  • 撮影日時と撮影場所の座標を特定したい。

 

撮影場所の特定

カメラ撮影時

CLLocationManagerを使って現在位置(CLLocation)を取得する。

フォトライブラリ利用時

画像データの持つExif内のGPSデータを利用する。

撮影場所の取得については特に問題ないと思う。
それぞれGPS情報が得られない場合はどうするのかはまた別に考える。

 

撮影日時の特定

まず撮影日時として使えそうな値が3つほどある。

  • GPS日付
  • システム日付
  • Exif撮影日時

 

それぞれの取得方法をざっくりまとめてみた。

  GPS日付 システム日付 Exif撮影日時
カメラ撮影時 CLLocation *location
[location timestamp]
(UTC)
[NSDate date]
(UTC)
DatetimeOriginalタグ
(タイムゾーンなしの現地時間)
フォトライブラリ
利用時
Exifの GPSデータ
DateStamp, TimeStamp
(UTC)
 × DatetimeOriginalタグ
(タイムゾーンなしの現地時間)

 

Exif撮影日時

本来、撮影日時といえばこのExifのDatetimeOriginalなんだろう。
でもこいつはタイムゾーンを持っていないという問題がある。

例えば、iPhone端末を持って国外へ行き、現地でタイムゾーン情報を取得した以降に撮影した写真の日時は現地時間となる。
東へ向かって旅行してタイムゾーンを跨ぐと、後に撮影した写真の日時が先の写真よりも前になる。

GPS情報が記録されていれば、タイムゾーンを判定してUTCへと変換することはできるかもしれない。
しかし、撮影日時は必ず現地のタイムゾーンで記録されてるんだろうか?
GPSは現地の位置で記録されていて、撮影日時は出発地点のタイムゾーンのまま記録されてしまっていた、ということはないんだろうか?
という疑問について、Exif情報への理解不足から確信がもてない。

システム日付

システム日付はフォトライブラリ利用時は意味が無いので使えない。
カメラ撮影時は別に使っても良いけど。

GPS日付

要件上、カメラ撮影時は撮影場所を特定するためにGPS情報を取得しているので、GPS日付は使用できる。

フォトライブラリ利用時は、GPS情報が記録されている画像を使用することが前提にはなるが、GPS日付を使用できる。

実はこのGPS日付もタイムゾーンを持っていないが、UTCということを前提に扱う。

 

現時点での結論

いろいろ理解不足な面があるので確信もてないところもあるが、写真画像データに関する仕様上、安定して使える日付情報は今のところないように見える。
とりあえず、現時点ではGPS日付を使って撮影日時を特定するのが最適だと判断。

 

参考

Exchangeable image file format

Exifファイル(4回目) ~ Exif IFD解説 ~

iPhoneの画像からEXIF,GPSデータを取得する

Get EXIF data of a particular image/photo in cameraroll


「Paddy: 風景を共有するアプリ」をリリースしました

長らく開発のお手伝いをさせていただいてたアプリが、ようやくのリリースとなりました。

風景写真を共有するアプリです。

家の近くで自分の知らない風景を見つけたり、旅先で地元の人しか知らない風景を知ることができたり、思わずそこに行ってみたくなるような風景を発見できたりします。

自分が見かけた気になる風景を気軽に撮ってシェアしてみてください。
風景写真と言っても、プロ写真家が撮るような超絶技巧の素晴らしい写真でなくても全然大丈夫です。

自分には当たり前の日常の景色が、他人にとってはそこへ行ってみたくなるような風景かもしれません。

リリースしたばかりで機能的にもまだまだ改善の余地がありますが、長く育っていけるアプリだと思います。

ぜひ使ってみてください。

(ご要望やバグを発見した際はお気軽にお知らせください。)


iPhone用福笑いアプリのサンプルプログラム(Swift版)

以前作ったサンプルプログラムをSwiftで書きなおし

福笑いアプリ

以前に福笑いを題材にサンプルアプリを作りました。

iPhone用福笑いアプリのサンプルプログラム

これは全てObjective-Cで書いてたので、Swiftで書きなおしてみました。

サンプルプログラム

福笑いiPhoneアプリサンプルプログラム Swift版

前回のコードはこちら
福笑いiPhoneアプリサンプルプログラム Objective-C版

ここ怪しいぞとか、ここはこうした方がもっと良くなるとか、いろいろご指摘いただけるとありがたいです。


【Parseメモ】BFTaskMultipleExceptionsExceptionリンクエラー

ParseSDKをver1.6.1からver1.6.4に更新したら以下のリンクエラーがでるようになった。


BFTaskMultipleExceptionsExceptionは、Bolts.frameworkの最新版(ver1.1.4)ではBFTask.hに

として定義されている。

しかし、現状の環境下で参照してるバージョンでは定義されていないらしい。

 

現状の環境は、

  • ParseSDK Ver1.6.4
  • FacebookSDK Ver3.20.0

Bolts.frameworkはFacebookSDKに含まれていて、このBolts.frameworkはver1.1.3であり、BFTask.hには上記の定数は定義されていない。

だからといって、Bolts.frameworkの最新版(ver1.1.4)を個別にリンクしようとすると、FacebookSDKが持つBolts.frameworkとduplicate symbols のリンクエラーを生じる。

FacebookSDKを最新版のver3.23.1にアップグレードしても、Bolts.frameworkのバージョンは同じくver1.1.3なので状況は変わらない。

FacebookSDKが参照しているBolts.frameworkを手動で最新版へ変更する手段が私には分からないので、ParseSDKのバージョンを元に戻して、FacebookSDK側の対応を待つことにする。

 

参考

Parse and facebook sdk -duplicate symbol


【Parseメモ】PFLogInViewControllerからTwitterログインしたアカウント情報を端末にも保存する

アカウントを端末へ保存

PFLogInViewControllerを使ってTwitterログインした際、アカウント情報を端末(設定アプリ)にも保存する方法を調べてみた。

発端

そもそもの発端は、Twitterにpostする画面としてSLComposeViewControllerを使おうとしたこと。そしてSLComposeViewControllerを使うには、端末に保存されたアカウントを必要とする。

前提

PFLogInViewControllerを使ってのTwitterログイン時、アカウントが端末に未登録の場合はWebViewベースの認証画面が表示され、アカウントを入力してログインする。

問題

この状態でSLComposeViewControllerを使おうとすると、端末へのアカウント登録を誘導するアラートが表示される。このアラートから設定アプリへ切り替えして登録することもできるが、ユーザーにとって登録が二度手間となるうえ、登録後に元のアプリへは自動で戻ってこれない。なのでユーザーが自分でアプリ切り替えをしないといけない。これらの動線は極力避けたかった。

アカウントの保存

ということで、PFLogInViewControllerでTwitterログインしたアカウント情報を使って端末にTwitterアカウントを保存する処理を調べて書いてみた。

 

まずはAccounts.frameworkをimportし、

 

Twitterログイン後に以下処理を行う。

 

これで端末上にアカウントが保存される。

 

ちなみに、同じ方法でFacebookアカウントも処理しようとしたが、

Error Domain=com.apple.accounts Code=7 “The application is not permitted to access Facebook accounts”

というエラーが発生して保存できない。
何かしらpermissionを与える方法があるのかどうか一通りネットでも調べてみたが、明確な情報はほとんどなく今のところお手上げ状態。

Facebookの基本的な認証システムを理解できていないのが要因かもしれない。


【Metaioメモ】Metaio製品を使ったモバイルARアプリ開発パターン

2015/6/1追記

Metaio社は2015年5月27日にホームページを更新。
その中で製品の提供中止についてアナウンスしている。

Product Support : metaio

日本国内でmetaio製品を販売・サポートしていたサイバネットシステム株式会社が運営するmetaio製品に関する日本語情報交換フォーラムでもアナウンスがあった。
こちらの方が本家よりも情報が細かく分かりやすい。
(中の人も今大変だろうな…)

Metaio社製品の販売中止について

Apple社がMetaio社を買収したという話もあるが、今のところ今後のサポート含め詳細は不明。

 

Metaio製品を使ったARアプリ開発

Metaio社が用意してくれているAR(Augmented Reality、拡張現実)開発環境がいろいろあって開発時の選択肢が分かりづらいので、適時少しずつまとめていく予定。

 

開発方法

大まかに分けて、ARアプリを開発するためには2種類の選択肢がある。
それぞれの詳細は後述。

 

トラッキング方法

現実環境を検出(トラッキング)する方法としては2種類に分けられる。

  • 光学トラッキング デバイスのカメラ映像を通してIDマーカーや写真・イメージ画像を認識、検出する。顔認識や3Dオブジェクトの検出もできるようになってきてる。
  • 非光学トラッキング デバイスのもつGPSやコンパスなどのセンサーを使って位置情報を取得する。

 

Junaioアプリの利用

概要

スマートフォン用ARブラウザアプリ。
iOS(App Store), Android(Google play)用にアプリが用意されている。
お手軽にAR体験ができる。

HTML + JavascriptベースのAREL (Augmented Reality Experience Language) を使ってUI作成もできる。

 

チャンネル

ARコンテンツの関連情報(コンテンツ名称や説明、コンテンツサーバURLなど)をJunaioサーバにチャンネルとして登録しておく。
metaio Developer Portal にアカウント登録することでチャンネル作成ができるようになる。

チャンネルは、IDマーカーやイメージ画像などを光学トラッキングする Image based (GLUE) channel と、位置情報に基いて非光学トラッキングする Location based channel の2種類がある。

JunaioアプリはARコンテンツを表示するために、まず該当のチャンネル情報を取得(検索やQRコードから読み込み)してコンテンツURLを特定し、そこからコンテンツをダウンロードする。

チャンネル情報の取得からコンテンツダウンロードまでは自動で行なわれるので、ユーザーはQRコードのスキャン操作するだけでAR体験できるようになる。

 

メリット

  • ARの基本機能(マーカー認識、コンテンツ描画)はアプリが行ってくれるので、コンテンツの作成に集中できる。
  • Metaio製品の中では一番お手軽かつ安価にARアプリを作れる。
  • Junaioアプリ自体は無料。
  • iPhone, Androidのクロスプラットフォームで開発できる。

 

デメリット

  • ARブラウザという性質上、他社のコンテンツも検索・表示できるため、自社コンテンツ専用アプリとしては使えない。
  • チャンネルデータを取得するためにUI周り(検索、QRコード読み込み)などはカスタマイズできない。
  • ARコンテンツを表示するために、まずチャンネルデータの読み込みを行う必要がある。そのためユーザー側からするとアプリを入手してすぐにARコンテンツを表示できないので、それらの工程を煩わしく感じる可能性がある。
  • オフラインで使用できない。

 

MetaioSDK の利用

概要

iOS, Android, Windows向けのARネイティブアプリを開発するためのキット

 

メリット

  • ARコンテンツデータをアプリ内に同梱できるので、オフラインで使用できるアプリを開発できる。
  • 要件に合わせたアプリを開発できる。
  • SDKを使って開発したアプリは無料で配信できる。
    ※ただしウォーターマーク、フラッシュスクリーンが表示される。
  • ARELを使って開発すれば、コンテンツ部分についてはプラットフォーム間で共通化できる。

 

デメリット

  • ARELを使って開発しない場合、要件上必要なプラットフォームごとにアプリを作らなければならない。
  • ウォーターマーク、フラッシュスクリーンを消すためにはSDKライセンスを購入する必要がある。
  • ネイティブアプリの開発、SDKライセンスの購入など、開発費が高額になりがち。

 

MetaioSDK + Cloud Plugin の利用

概要

MetaioSDKでネイティブアプリを開発し、コンテンツ配信はJunaioチャンネルを利用できる。

 

メリット

  • サーバ上に設置したARコンテンツを取得する部分はCloud Pluginにお任せできる。(Junaioと同じ挙動)
  • 無料で配信できる。
    ※ただしウォーターマークが表示される。

 

デメリット

  • ウォーターマークを消すためにはMetaio Cloud(月額)を契約する必要がある。
  • オンライン環境が必要。

 

参考

metaio Developer Portal

AR/VRソフトウェア(拡張現実・バーチャルリアリティソフトウェア):サイバネット


【Parseメモ】Crash Reporting

クラッシュログを収集。

機能を有効にするには、Parse app keys を initialize する前に以下のコードを入れる。

一度有効にしておくと、クラッシュレポートは再起動時にParse側に送信され、analytics dashboard上で確認することができようになる。

 

symbolicate

クラッシュログの中のシンボルを読める状態にしてクラッシュログを分析しやすくする。そのためににsymbolファイルをParseへ送信しておく。

送信方法は2つ

1.手動で送信

$ parse symbols <dSYM/xcarchive/DWARF path>

→pathの指定の仕方が良く分からない。dSYMファイルを探さないといけないっぽい。

2.自動的に送信(Parse推奨)

Xcodeがビルド時にsymbolファイルを自動的にParseへ送信してくれる。便利。

手順としては、
1.Parse Cloud Code directoryを作成。
2.Build Phases で Run Script 設定

Run Scriptの設定については参考サイトの動画が分かりやすい。

Parse Quick Start Install the SDK

 

Analytics dashboard Crashes

テスト的に AppDelegate の application:didFinishLaunchingWithOptions:の中でNSExceptionを発生させてみた。

リスト

screenshot

 

詳細:symbolなし

screenshot

symbolなしだとどこで例外が発生したのか分かりにくい。
symbolicateさせるためにdSYMファイルを送信することを促すメッセージが表示されている。

 

詳細:symbolあり

screenshot

symbolありだと、AppDelegateのメソッド内で何かが起きたことがなんとなく分かる。

 

参考

Parse Developer Guide | Crash Reporting

Parse Quick Start Install the SDK


【Parseメモ】PFUserオブジェクトへの他ユーザーからの書込権限は追加できない

PFUserのACLに、Roleによる編集権限を追加しようとしたらエラー発生。

 

 

エラー

error: user objects cannot allow writes from other users

ユーザーオブジェクトには、他のユーザーから編集できるようになる権限を付与できないので、ユーザーオブジェクトを編集するような処理は Cloud Code で master key 使ってやれということのようだ。

 

参考

iOS; Allow admin user write access to another user