jarinosuke blog

about software engineering, mostly about iOS

UIViewTintAdjustmentMode について

tintColor

iOS 4 以前は tintColor プロパティは UIToolBar など、限られたクラスにのみ提供されていました。

UIToolBar - tintColor | iOS Developer Library

iOS 5 になると UIAppearance が提供され、他にもたくさんの UIView のサブクラスが tintColor プロパティを持つようになりました。

iOS 7 では遂に UIView 自身が tintColor プロパティを持つようになり、アプリケーション全体への tintColor の反映が可能なりました。

どういうことかというと、値を明示的に指定しない限り tintColor プロパティは親ビューの値を受け継ぐので、

たとえば keyWindow の tintColor プロパティを設定するだけでアプリ全体に行き渡る、ということです。

UIViewTintAdjustmentMode

iOS 7 からは tintColor 同様、UIView に tintAdjustmentMode というプロパティが追加されました。

このプロパティは上記の tintColor の継承関係をどのように反映させるかを決定するものです。

subviews の中に tintColor プロパティがデフォルトのものしか無ければ値は UIViewTintAdjustmentModeNormal になります。

UIViewTintAdjustmentModeDimmed を明示的に tintAdjustmentMode に設定すると、

その UIView の tintColor からは dimmed 加工が施された UIColor が return されるようになります。

ユースケース

f:id:jarinosuke0808:20140406193757p:plain

そもそもこのプロパティを見つけるに至ったきっかけになるのですが、

UIAlertView のようなモーダルで覆うカスタムビューを作る場合などに使用します。

以下のコードが非常に勉強になりました。

TeehanLax/TLAlertView

ちなみに UIAlertView を show したときに後ろ側に回る keyWindow を見るとわかりますが、

UIAlertView はしっかり keyWindow の tintAdjustmentMode を dimmed に設定しています。

なので UIKit の作法に従うためにも、細かいですがしっかりと実装していきたいところですね。

参考

UIView - tintAdjustmentMode | iOS Developer Library

[iOS 7] UIViewにtintColorが追加されました!| Developer.IO

Adopting iOS 7 APIs

TeehanLax/TLAlertView

UIAppearance | NSHipster

Asset Catalog の AppIcon を使って複数ターゲットで出し分ける

Asset Catalog 以前

Asset Catalog が出るまでは、アプリのアイコンをターゲット毎に出し分ける際は

以前に僕が書いた

アプリの情報をアイコンにオーバーレイさせる方法

と同じ要領で、ビルド後のスクリプトを用いてターゲット毎に用意された画像を適宜配置する必要がありました。

Asset Catalog 以後

Xcode 5 から Asset Catalog という画像管理に便利な機能が追加されました。

Xcode 5 で新しくプロジェクトを作成すると、Images.xcassets というフォルダがデフォルトで作成されます。

内部には AppIcon と LaunchImage という Image Set があり、これらに画像を適用するといった具合です。

画像の slicing を直感的に指定できたり、AppIcon も iOS/iPad 毎、iOS のバージョン毎に指定できたりと便利です。

Asset Catalog を用いたアイコン出し分け

では上記の AppIcon や Launch Image を出し分けるかという肝心な所ですが、

Build Settings を覗くと、 以下の項目がある事に気付くかと思います。

Asset Catalog Compiler - Options

その中に、

Asset Catalog App Icon Set Name
Asset Catalog Launch Image Set Name

という設定項目があり、デフォルトでは AppIcon と LaunchImage が設定されています。

これを ReleaseAppIcon などの自身で設定した Image Set 名に設定する事で、

ターゲット毎に Image Set を変更する事が可能になります。

ちなみに xcconfig などで書くのであれば、上記2項目のディレクティブは以下です。

ASSETCATALOG_COMPILER_APPICON_NAME
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME

Asset Catalog のとても残念な所

ここまで Asset Catalog の良い所だけ書いてきましたが、実のところ残念な所も多いです。

たとえば上記で行ったターゲット毎の Image Set の出し分けを、

アプリ内で利用するリソースに対しても行うのは非常に困難で、

結局ビルド後のスクリプトで Images.xcassets 配下の画像リソースを上書きする手間が出てきます。

詳細は下書き程度に書いた僕のブログを読んでください。

Asset Catalogs with Multiple Targets | jarinosuke stash

iOS 7.1 から iAd 経由でのアプリインストールのコンバージョン計測が可能に

コンバージョン計測

iOS 7.1 から以下の API が iAd.framework に追加されています。

iOS 7.1 API Diffs

ADClient

- (void)determineAppInstallationAttributionWithCompletionHandler:(void (^)(BOOL appInstallationWasAttributedToiAd))completionHandler NS_AVAILABLE_IOS(7_1);

この completionHandler を登録しておくと、 iAd 経由でユーザがアプリをインストールした場合に発火するといった具合です。

また設定において、Limit Ad Tracking を行い、広告トラッキングをオプトアウトしている場合には appInstallationWasAttributedToiAd が NO で発火するようです。

iAd の発展

iOS 6 から advertisingIdentifier が追加され、UDID や MAC Address の取得が禁止になり、 iOS 7 ではiAd の導入が劇的に簡単になりました。

以下のような噂(1年前の記事ですが)も立っているようなので、今後も Apple の広告への取り組みは注目されそうです。

Appleがクッキーを利用しているアプリを拒絶へ: Ad Identifierへの統一がねらい

参考

AdとID周辺の動き

iAd 実装が iOS7 から恐ろしく簡単になってる件

iAd on iOS 7

iOS 6 までは iAd を表示しようとすると、ADBannerView をインスタンス化して layout してなど色々と面倒でした。

iOS 7 では iAd.framework に以下のカテゴリが追加されています。

UIViewController (iAdAdditions)

これを用いる事で、今までのような煩わしいことをほとんど気にせずに iAd を表示する事が出来る様になります。

ユースケース毎に見ていきましょう。

バナー広告を表示したい

以下のプロパティをセットするだけ。

///(1)フレームワークをimport
@import iAd;

///(2)初期化時などに
self.canDisplayBannerAds = YES;

これだけでバナーが画面下に表示されます。

Interstitial 広告を表示したい

事前準備として以下を実行すると Interstitial 広告の情報をプリフェッチしておいてくれます。

//起動時などに
[UIViewController prepareInterstitialAds];

自動的に出すだけならカテゴリで追加された UIViewController の以下のセットするだけです。

@import iAd;

self.interstitialPresentationPolicy = ADInterstitialPresentationPolicyAutomatic;

自動だとさすがに煩わしい、意図したタイミングで、という場合は以下の様に

@import iAd;

self.interstitialPresentationPolicy =  ADInterstitialPresentationPolicyManual;

//意図したタイミングで
[self requestInterstitialAdPresentation];

iAd という選択肢

「iAd だけじゃやってけない」、「SSP 使って出し分けしたいし」、「広告興味ありません」などの意見には、

上記だけでは充分なメリットはないですが、

「広告導入に手間はかけずに、プロダクトに注力したい」「けど最低限の運営費は欲しい」みたいな開発者には一つの手段には成り得ると思います。

ということで知らない間に驚くほど簡単になってた iAd の紹介でした。

iAd Production Beginner’s Guide

iAd Production Beginner’s Guide

Framework Bundle について

framework ファイルってナニモノ?

iOS 開発をするうえで、プロジェクト作成時点で Foundation.framework や UIKit.framework などの

Apple から提供されている framework が既に追加されているかと思います。

普段あまり疑問に思わずこれらの framework を使わせてもらっていますが、

いざこれを作ろうと思うと、そもそも .framework ファイルとはナニモノで、

どうやって作れば良いのか分からなかったので、この記事を書きました。

上記で .framework ファイルと呼んでいたものは正式には Framework Bundle と言います。

指定されたディレクトリ階層にリソースファイルや Static Library やドキュメントなど、

色々なものをパッケージングしてカプセル化して提供しているディレクトリを Framework Bundle と呼ばれています。

Framework Bundle で提供するメリット

前回の記事でも紹介した Static Library で提供するよりも、

Framework Bundle の方が以下のようなメリットがあります。

  • インストールが手軽

Static Library はヘッダやライブラリなど複数ファイルを追加しないといけないですが、

Framework Bundle は、それ自身を追加するだけ済みます。

  • 様々なリソースが追加可能

画像やドキュメントなども追加できます。

  • 複数バージョンを含む事が可能

同じ Framework Bundle 内に、 複数のバージョンを持つ事ができるので

この Framework を使用するプロジェクトの古いプログラムに対しての下位互換を可能にします。

このように Framework Bundle は良い事ずくめです。

しかし Framework Bundle で提供する際のデメリットもあります。

Xcode には iOS 向けの Framework 用のプロジェクトテンプレートが存在しないので、

自身で Framework Bundle を生成しないといけない点です。

Mac には Cocoa Framework テンプレートがあるのですが、iOS にはありません。

しかし、その部分は実績のある OSS が代替してくれるので心配は不要です。

以下からは Framework Bundle の構造を読み解き、どのような方針でそれを作成すれば良いかをみていきます。

ではまず、Framework Bundle がどんなデータ構造を取っているのかを見てみましょう。

Framework Bundle のファイル構造

ファイル構造といってもそこまで難しい事は何もありません。

早速みてみましょう。

MyFramework.framework/
    MyFramework  -> Versions/Current/MyFramework
    Resources    -> Versions/Current/Resources
    Versions/
        A/
            MyFramework
            Resources/
                English.lproj/
                    InfoPlist.strings
                Info.plist
        B/
            MyFramework
            Resources/
                English.lproj/
                    InfoPlist.strings
                Info.plist
        Current  -> B 

階層毎に見ていきます。

MyFramework.framework 配下には実体のあるディレクトリは Versions のみです。

ではその Versions には何が入っているかというと、

Version 毎に分かれた A, B というディレクトリ、そして現在の Current を示すシンボリックリンクです。

この Current を通して、一番上の階層にあった MyFramework と Resources は参照している訳です。

これはほんの一例です。詳細は以下のリンクを読んでみてください。

Anatomy of Framework Bundles

Framework Bundle の作り方

では実際に Framework Bundle をどう作るのか、という一番大事なところに触れましょう。

自分でスクリプトを作成し、 Framework Bundle を生成する事も出来ますが、

以下の OSS を用いる事で簡単に出来ます。

iOS-Universal-Framework

上記の OSS を用いて、iOS 用のプロジェクトテンプレートを作成するだけです。

長くなってしまうので、 iOS-Universal-Framework

実際の使い方などは別の記事に回したいと思います。

参考

Framework Programming Guide

Xcode 4におけるiOS Frameworkの作成方法

Xcode Build Settings Reference

xcodebuild man page

iOS-Universal-Framework