iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
Macintoshが革新的だったのは、白色背景に黒文字を表示したことだ。これは、macOSのAquaにも受け継がれたのだが、MojaveのDark Mode登場により状況が変わった。説明を信じれば集中したいときはDark Modeが適しているそうだ。
真偽はさておいて、Dark Modeに試してみて感じるのは、Dark Modeに完全対応していないアプリケーションが存在すると、画面が見苦しくなるということ。
今回の発表では、Dark Modeへの対応方法を駆け足で紹介してみる。
システム環境設定で、従来のlightとdarkは切り替えらる。ということは、切り替えに追従して表示を変更できるようにしないといけない、ということになる。
ユーザインタフェースに使う色を直接記述してしまうと外観モードの切り替えに対応できないのは当然だ。NSColorではユーザインタフェースのために以下のような色指定を用意している。
また、Color Set assetを独自に定義できる。
これを以下のように利用する。
let aColor = NSColor(named: NSColor.Name("MyColor"))
以下は、色の定数を利用した例だ。
override func updateLayer() {
self.layer?.backgroundColor = NSColor.textBackgroundColor.cgColor
}
GDPRで話題になる頻度が上がったプライバシーとセキュリティ。対応は個々でだと思うが、サーバを利用しない方が難しい今のスマートフォン・アプリケーション開発者にとって、システム提供側によって、何らかの対応が必要になる可能性がある。そこで、今回の発表では、iOSアプリケーション開発に関係がありそうな項目について取り上げてみた。
対象は個人情報。内容は、思いっきり端折ると、利用目的など、同意を得ないといけないのと、EEAで得られた情報を第三國へ移転するのは禁止だ。
Data and Privacy(https://privacy.apple.com/)というページが用意されているが、これはApple製品向けで、サードパーティの開発者向けの情報でない。
iOS 11.3 で、GDPR相当のプライバシー保護機能を搭載したので、各アプリ/サービスは、個々で判断して対応しろということだろう。
GoogleはFirebaseサービスを利用した開発者向けに、Firebase のプライバシーとセキュリティ(https://firebase.google.com/support/privacy/?hl=ja)というページを用意している。
このページでは、Googleの対応内容と開発向けについて説明がある。我々アプリケーション開発者が関係する後者について、ざっと抜き出してみる。
Firebaseの個々のサービスで扱い個人情報は、以下のとおり。
Firebaseサービス | 個人情報 |
---|---|
Cloud Functions for Firebase | IP addresses |
Firebase Authentication | Passwords Email addresses Phone numbers User agents IP addresses |
Firebase Cloud Messaging | Instance IDs |
Firebase Crash Reporting | Instance IDs Crash traces |
Firebase Crashlytics | |
Firebase Dynamic Links | Device specs (iOS) |
Firebase Hosting | IP addresses |
Firebase Invites | Device specs (iOS) Locally-stored contacts |
Firebase Performance Monitoring | Instance IDs IP addresses |
Firebase Predictions | Instance IDs |
Firebase Realtime Database | IP addresses User agents |
Firebase Remote Config | Instance IDs |
Google Analytics for Firebase | Mobile ad IDs IDFVs/Android IDs Instance IDs Analytics App Instance IDs |
ML Kit for Firebase | Uploaded Images |
以下について、開発者の対応方法が説明されている。
この中から、iOSと関係が深いと考えたものについて、もう少し深く調べてみる。
Firebase Cloud Message (FCM) は、iOSのリモート通知に似た位置付けのサービスだ。FCMはインスタンスIDを生成し、それを登録トークンとして利用する。このインスタンスIDが、iOSリモート通知のデバイス・トークンに相当する。このインスタンスIDはアプリケーションをインストールした後にアプリケーションを起動すると自動で生成される。
この良かれと考えて用意した機能が仇になったのか、自動初期化を禁止する方法が用意された。AndroidManifest.xmlに以下の設定を行うと、自動初期化は禁止となる。
<?xml version="1.0" encoding="utf-8"?≶
<application≶
<meta-data android:name="firebase_messaging_auto_init_enabled"
android:value="false" /≶
</application≶
例えば、ユーザにクラウド・メッセージの利用を確認してOKとなった場合、以下のコードで自動初期化は有効となる。
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
この有効/無効の設定はシステムによって保持されるので、例えば、ユーザへの確認結果を記録する方法として利用できると考えられる。
ちなみに、現在のインスタンスIDは以下のコードで取得することができる。
FirebaseInstanceId.getInstance().getToken()
これについて、動作確認をして分かったことがあるのだが、正しいのか自信がないため、発表資料では説明しないので、興味がある方は、勉強会で質問してほしい。
上記は、Firebase Cloud Messageの場合だが、iOSのリモート通知のデバイス・トークンも個人情報として、同様な考えて扱うべきだと考えられるので、Firebaseの情報は参考になると思う。
Firebaseはクロスプラットフォームなサービスなので、iOSアプリケーションでも利用している場合があると思うが、今回の件で気をつけないといけないことがある。
Firebaseのアナリティックスは明示的に利用するコードを書かなくても、アナリティックスの収取を行なっている。また、広告IDの収集も行なっている。
Androidで収集を完全に無効にする場合は、AndroidManifest.xmlに以下の設定を行う。
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" /≶
Androidで広告IDの収集を無効にする場合は、AndroidManifest.xmlに以下の設定を行う。
<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" /≶
iOSの場合、Info.plistにFIREBASE_ANALYTICS_COLLECTION_DEACTIVATEDをYESで定義すると収集が完全に無効になる。そして収集を再び有効にするには、この定義を削除すればいいみたいだ
とても違和感を感じる用語がある。それは、『参照渡しだ』。
え!違うだろ?と感じていたが、いい機会なので、調べてみた。
引数と呼ばれるものにどんな種類があるのか、まずは列挙してみる。
関数に渡す値。
sum(1, 2);
関数が受け取った変数。
int sum(int a, int b)
{
return a + b;
}
値が渡される。
_ <h2>ポインタ渡し
渡す値がアドレスの値渡し。
Pascalでは,値渡し(call by value)と変数渡し(call by variable)が存在し、変数渡しは参照渡しに相当する。
そもそもは、変数渡しの実装方法に参照渡しがある。参照渡しは、変数に対する参照(アドレス情報)を渡す方法だ。
Inside Macintoshは、コードはPascalで記載されているが、それをC言語で利用する場合、varがついた変数渡しの引数は、C言語ではポインターと読み替えていた。
具体的には、Inside Macintoshで以下のようにPascalで説明されていたとする。
PROCEDURE GetPort(VAR port: GrafPtr);
これをC言語では、以下のように読み替える。
void GetPort (GrafPtr * port);
C言語の関数の引数は全て値渡し。K&Rでしっかりと説明されている。
ポインタでアドレスの値を渡すのを参照渡しと呼ぶのは間違いだ。
Javaも全て値渡し。
ポインタ演算ができない、アドレス(参照)の値渡しが利用できるが、これを参照渡しと呼ぶのは、如何なものか。
値渡しに加え、本物の参照渡しが存在する。
void time_two(int& a)
{
a *= 2;
}
また、C++11では右辺値参照・ムーブセマンティクスという所有者の移動が用意されている。
二つの参照渡しの方法が用意されている。
int initializeInMethod = 0; // 初期化が必須
OutArgExample(initializeInMethod);
Console.WriteLine(initializeInMethod);
void OutArgExample(ref int number)
{
number = 44;
}
int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);
void OutArgExample(out int number)
{
number = 44; // 代入が必須
}
refは変数が渡されるので、初期化によって値が設定されていない変数はNGだ。
outは値を返すという意味から、初期化は必須でないか、関数内で値を必ず設定しないといけない。
値渡しだが、inoutキーワードをつけると値呼びの結果返し(call-by-value-result)となる。
C言語のポインターの場合と同様に、変数が参照型の場合、参照の値渡しにより値を変更できる。
class Demo {
public var num = 0;
}
func set999(a: Demo) {
a.num = 999;
}
let demo = Demo()
set999(demo)
値呼びの結果返しの例。
func set999(a: inout Int) {
a =999
}
var num = 0
set999(&num)