【Kotlin】R.layout.activity_mainでunresolved referenceというエラー?

Kotlinに手を出しました。\(^o^)/
未だにSwiftもまともに使えてないですが、Androidアプリも作りたいなーってことでボチボチと勉強を始めます。

とりあえず本を一冊買ってきて写経から始めます。(-人-)
買った本はこちら。

【Kotlin】R.layout.activity mainでunresolved referenceというエラー?

はじめてのAndroidプログラミング 第3版 [ 金田 浩明 ]
価格:2862円(税込、送料無料) (2019/1/13時点)

Android Studioのインストールから初期設定まで良い感じです。
Android StudioはXcodeとはやはり使い勝手がちがって戸惑うところも多いですね。

インストールから、HelloWorldを終わっていよいよ簡単なアプリを作っていくところで本に出てないエラーで引っかかりました。
じゃんけんアプリを作っていて、画像を配置し終わって、コードを書くところです。
上記の本を持ってる人だったら、127ページ辺りです。

コードのViewという部分が赤くなって、android.view.Viewが自動インポートに失敗している場合というのは本に対応策が載っていて対処できたのですが、その上の、R.layout.activity_main のRが赤い字になっていて何らかのエラーを起こしているようでそこで数時間悩んでしまったのでその備忘録です。
こんな感じ。
【Kotlin】R.layout.activity mainでunresolved referenceというエラー?

ぐぐってみるとR.javaがないって事らしい。
でもそれは自動インポートされるもので手動で入れるものでもないらしい。
XMLが間違ってるとR.javaはインポートされないとかなんとか。
MainActivity.ktのコードを書いていてのエラーなので、activity_main.xmlをひらいてテキスト表示でコードで見てもエラーはない。

でいろいろと良く見て調べていくと、activity_main.xmlではなく、activity_result.xmlの方でエラーが見つかった。
【Kotlin】R.layout.activity mainでunresolved referenceというエラー?

画像ボタンの幅や高さの数値の単位を付けていないことが原因らしい。
そのくらい自動で直してくれよと思わんでもないが、そういう仕様ならば仕方がない。
数値にdpをつけて修正。

BuildからClean Projectを選ぶとエラーが無くなった。
【Kotlin】R.layout.activity mainでunresolved referenceというエラー?

Xcodeとはいろいろとお作法が違うので大変だが、それもまた楽し!ということにしておこう。

【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

設定画面とか縦長でスクロールする画面を作りたい時ってあるじゃないですか。
でもテーブルビュー使うのめんどくさいな、みたいな。
そんなときに便利なやり方です。

一応の完成形はこんな感じ。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

参考サイト
制約の修正なしで縦方向に要素を追加可能なビューの作成 – Qiita
【iOS】ちょっと待って!その画面UITableViewで作る必要ないかも – ペンギン村 Tech Blog
【UIScrollView】Autolayoutで縦スクロール【Xcode8.x】 – Qiita

ではまず、Safe AreaにScroll Viewを配置します。
Add New Constraintsで上下左右全てのマージンを0とします。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

次いで、その中にVertical Stack Viewを配置し、Scroll Viewと同様に、Add New Constraintsで上下左右全てのマージンを0とします。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

このままではScroll Viewのコンテントサイズの制約がないためエラーがでます。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

マウスの右ボタンでStack ViewからScroll ViewへドラッグしてEqual Widthで横幅を揃える制限をつけます。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

Stack Viewの子コンテンツでScroll Viewの高さが決まります。
とりあえずStack ViewのDistributionをEqual SpacingにしてSpacingを0にします。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

子コンテンツを入れて高さが決まるとScroll Viewの高さが決まります。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

さて、ここから縦長な画面にします。
操作するViewを選んで、simulated sizeを「freeform」にして、heightを設定します。
とりあえず1200にしてみました。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

StackViewに高さが200の子Viewを6個入れて分かりやすように色を付けてみました。
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

これでアプリを起動すると綺麗にスクロールしました。\(^o^)/
【Swift4】縦長のスクロール画面をscrollViewとstackViewを使って作る。

これだけのことがコードを一行も書かずにできるってすごいなーと思います。\(^o^)/

【Swift4】NSDictionaryを要素に持つNSMutableArrayをDictionaryのKey順にソート

自分は独学でiPhoneアプリを作っています。
初心者向けのSwiftの本を数冊とあとはインターネットで検索して調べています。
C言語の基礎知識とかはまったくないです。英語のApple Developerなんちゃらを読んでもさっぱり理解できません。
しかし、やりたいことが決まって大体のやりかたはネットで調べれば基本的なことはたいてい出てきますが、
たまにこの人どーやって調べてこのやり方にたどり着いたんだろうと思うことがたまにあります。
今回もそんな感じです。
そして自分はすぐに忘れてしまうし、先人のブログが消えるとわからなくなるのでここに劣化コピーを載せています。

今回は、配列に入ったディクショナリをその要素でソートしたかったんですが、なかなかやり方が分からず難儀しました。
今回の参考サイトはこちら。
[swift] NSDictionaryを要素に持つNSArray/NSMutableArrayをKey順にソート | BlueBear I/O

適当に調べながらプレイグラウンドでコードを書いたので冗長だったりするかも。
サンプルコード

ほんとこーゆーのってどうやってしらべてるんだろう?
とりあえずなんとかなってよかった。
うじゃうじゃ。

【Swift4】機器がiPhoneかiPadかを判定。画面サイズでも判定。

参考サイト
【Swift4】iPhone・iPadなどの機種判定し処理を振り分ける方法【iOS9】 | ニートに憧れるプログラム日記

上記ページでもSwift4と書かれているが自分の環境ではうまく行かなかったので、試行錯誤した。
UIDevice.current.model で取得できるようだ。
あと、appleTVとcarPlayの場合何を返すのか確定できなかったので割愛した。

更に画面サイズで、細かいサイズ判定ができる。
画面が縦向きか横向きかで高さが変わるのでそれも考慮。

機種も変数で返してくれたら良いのになー。
うじゃうじゃ。

追記。
google Analytictから吐き出されるログを見てたら

“&dm” = “iPhone10,3″;
“&ds” = app;
“&sr” = 1125×2436;
“&t” = screenview; 

とゆーぶぶんが。
なんかで判定はできるんやろな。
うじゃうじゃ。

追記。2018/12/24
[iOS][Android][Tips] デバイスモデル名を取得する | DevelopersIO
上記サイトを見ると、C 言語のライブラリ関数である utsname を使用 するとわかるそうですが、
私には何のことかよくわかりませんでした。/(^o^)\

【Swift4】【autoLayout】レイアウトが決まってからの変更処理のタイミング

「autoLayoutってなんじゃー!つかいもんにならんわー!」
と、そんなふうに思っていた時期が僕にもありました。(笑)

使い慣れてみるとケッコー便利です。\(^o^)/

さて、そんな便利なautoLayoutですが、一つ困ったことが。
画面のサイズが決定して、それをもとに%などでサイズが決まって形状を変えたいときなどどの段階で処理するかが問題なのです。

viewControllerで描画に関連しそうなメソッドのライフサイクルはこんな感じかな?

さて、autoLayoutでのレイアウトが決定しているのがviewDidLayoutSubviews以降です。
それ以前は値が決定しておらず、autoLayoutで決まる値を参照にするとおかしなことになる可能性が高いです。

viewDidLayoutSubviewsを知る前はviewDidAppearにその処理を書いていました。
しかし、ビューが描画されたあとなので、一瞬描き変えられるところが見えたりします。/(^o^)\

また、毎回他のビューから戻ってきてビューが表示されるたびに同じ処理を繰り返してしまいます。
レイアウトが決まってビューが表示される直前のviewDidLayoutSubviewsなら描き変えられるところは表示されませんが、
こちらはビューの切り替わりだけでなくビューが回転したりイベントあるたびに呼ばれてしまうようです。

で、本題。
結局やりたいのはviewDidLayoutSubviewsで一回だけ処理をさせるということ。
いろいろと調べてこちらのサイトが参考になりました。

[Swift] viewDidLayoutSubviewsで初回だけ処理をしたい | 黒ごまのおむすび

Lazyというのをつかうらじいです。/(^o^)\

この処理だとビューの表示前に一回だけ呼び出すことができました。
他の人はこんな場合どうしているんだろう?
うじゃうじゃ。/(^o^)\

【Swift4】【CallKit】CXCall、電話の発着信等を取得する。

電話の着信時、受話時、終話時をアプリで受け取りたかったので調べてみた。
参考サイト

Xcode|iOS10から新しく加わったCallkitを使って通話の状態を取得してみた

上記サイトが役に立ちました。
ただ、Objective-cだったのでSwiftに変更。

CallKitのCXCallObserverのデリゲートでCXCallの値で送られてくるようだ。

CXCall – CallKit | Apple Developer Documentation
デベロッパサイトを見てgoogle翻訳

var uuid:UUID
コールの一意の識別子。
(よくわからん、とりあえず無視の方向で。w)

var isOutgoing:Bool
呼び出しが発信かどうかを示すブール値。
(コールが発信中か受信中か?)

var hasConnected:Bool
呼び出しが接続されているかどうかを示すブール値。
(通話中かどうか?)

var hasEnded:Bool
呼び出しが終了したかどうかを示すブール値。
(通話が終了したかどうか。)

var isOnHold:Bool
通話が保留状態かどうかを示すブール値。
(保留中?)

状態の変化があったときこれらの組み合わせで通知が来るようだ。
ちょっとややこしい。

とりあえずアプリで受けたいのは「着信」「受話」「終話」
なので下記のような感じで試してみた。

これで、家電からiPhoneに電話。「着信」「受話」「保留」「保留解除」「終話」と、「着信」から受けずに電話を切って「終話」。とやってみた。

まず着信
  通知があったよ!
  isOutgoing false
  hasConnected false
  hasEnded false
  isOnHold false

すべてfalseの通知が来ます。

続いてそこから電話を受けます。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded false
  isOnHold false

保留にします。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded false
  isOnHold true

保留を終わります。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded false
  isOnHold false

電話を切ります。
  通知があったよ!
  isOutgoing false
  hasConnected true
  hasEnded true
  isOnHold false

もう一度着信は同じなので割愛して、電話を受けずに切った場合。
  通知があったよ!
  isOutgoing false
  hasConnected false
  hasEnded true
  isOnHold false

こうして見ると、hasConnectedだけでは「電話に出たとき」か「通話の終了」の通知かはわからず、hasEndedを含める必要があるのがわかります。
あ、しかも、これじゃ、着信から電話に出たのか、保留から電話にもどったかわからないじゃん。/(^o^)\
そこを区別するにはこちら側でなにか記録して区別するしか無いですね。

ところで、iPhoneの保留ってどうするか知ってますか?
試そうと思って家電からiPhoneに受話してみたが、保留の機能が見つからない!/(^o^)\
仕方ないので一旦切って調べてみると、「消音」の長押しだそうだ。
試そうと思って家電からiPhoneに受話してみたが、長押ししてみても保留にならない!/(^o^)\
仕方ないので一旦切って調べてみると、「消音」の3秒位長押しだそうだ。
そしてもういっかい試してみたらちゃんとできました。/(^o^)\
古い情報だと保留中は電子音とか書いてありますが、先程試した時は日本語で「保留中ですお待ち下さい」から音楽になっていました。
あと、通話中のスクリーンショットを撮ろうと思ったのですが、
通話する、「音量UP+サイドキー」を押すで、電話が切れる!/(^o^)\
タイミング悪かったかなと再度通話する、「音量UP+サイドキー」で、電話が切れる!/(^o^)\
どうも通話中はスクリーンショットが撮れないようです。
ちなみに画面収録も着話したら録画が切れました。通話中は記録できないようです。
なんかすっごい電話代無駄にした気がする。/(^o^)\

閑話休題/(^o^)\それはさておき、

形にしてみよう。
受話状態になったらこれを参考に
【Swift4】NotificationCenterの備忘録。 | iPhoneアプリ備忘録
通知が来るようにしてみた。

メイン画面にはLabelを。

電話を通知する方のクラス。

こんな感じで実現できました。\(^o^)/
GitHubが使えればコードをアップできるらしいけどよくわかんないんだよね。/(^o^)\

【Swift4】【UIDatePicker】のバグふたたび。UIDatePickerMode .countDownTimer

Swiftには、いや、Xcodeにはバグが有る。
2年前にもObjective-Cで泣かされた。
その時はなんとかなったけどそのバグはSwiftになっても直ってなかった。
とゆーか、よりひどくなってた。

そのバグはUIDatePickerのcountDownTimerモードにある。
マイナーすぎて使い所無い機能なのか、それ自体の情報も少ない。

UIDatePickerのcountDownTimerモードというのは、その名の通り、
24時間までのカウントダウンの時間を設定するためのピッカーだ。
ピッカーで10分と設定すると600秒の値が渡される。

さて、そのバグというのはピッカーで数値を決めても一回目のときはスルーされてしまうとゆーものだ。
二回目以降はちゃんとデータが渡されるのだが、一回目はスルーされてしまう。
10分を選んでも全然反映されない。
そのため、例えば10分に設定したい時は、一度11分にしてから10分にするなどというとてもめんどくさいことになる。
そんな状態ではとてもリリースできたものではない。

ネットを調べてみるといくつか情報はある。
古いのはこちら。
ios – UIDatePicker bug? UIControlEventValueChanged after hitting minimum internal – Stack Overflow
どうもiOS7の頃からあるバグらしい。
一応解決策も提示してあり、僕も2年くらい前にお世話になった。
割りと最近の記事ではこちら。
Xcode – DatePickerの値選択時の表示エラーが直らない|teratail
こちらはswift3での解決策が示してある。ま、Objective-cからSwiftに変わっただけでやってることは同じ。

そちらを参考にしてピッカーのモードをカウントダウンタイマーにしたあと、
バグ回避のためDispatchQueue処理を入れてみた。
(下記参照)

自分だけなのか、Swift4以降の仕様なのかこの状態ではやはり一回目の設定はスルーされた。
半日ほど試行錯誤したがどうしてもうまくいかない。
そんな中、キーボードを仕舞ってまたキーボードを出したときもまた同じく一回目がスルーされていることに気づく。

そうであれば、キーボードが出たときにバグの回避処置を入れればなんとかなるのでは無いか。
とゆーことで、ノーティフィケーションをつかい、キーボードが出たときに回避処置が入るようにしてみた。

こんな感じ。

結果は見事成功!\(^o^)/
なんとかカウントダウンのピッカーが使えるようになった。

時期に忘れてしまうと思うので備忘録として残しておく。/(^o^)\
あと、誰かの参考になったら嬉しい。

【App Store】ガイドライン 5.3 賭博ゲーム、ギャンブル、宝くじ/ロト

前回、古いアプリがガイドライン4.3スパムであると、判断されて公開停止になったと書きました。
んで、「かたっぽ削除するからえーやろ」って返事を書いたら斜め上の返事が来ました。

その内容はこちら。

App Store Review

Hello,

Thank you for your responses. In order to reduce fraudulent activity on the App Store and comply with government requests to address illegal online gambling activity, we are no longer allowing gambling apps submitted by individual developers. This includes both real money gambling apps as well as apps that simulate a gambling experience.

For this reason the apps will not be made available for sale at this time.

Best regards,

ググる翻訳すると、

App Storeレビュー

こんにちは、

ご回答いただきありがとうございます。 App Storeでの不正行為を減らし、違法なオンラインギャンブル活動に対処する政府の要請に従うため、個々の開発者から提出されたギャンブルアプリは許可されなくなりました。 これには、リアルマネーギャンブルアプリとギャンブル体験をシミュレートするアプリの両方が含まれます。

このため、この時点でアプリを販売することはできません。

宜しくお願いします、

どうやらApp Storeではくじ引きや抽選を含むギャンブル系のアプリがだめになったっぽいです。
他のサイトでもそのようなことが書いてありました。
一斉摘発のようですね。

参考サイト
【iPhone】App Storeでギャンブル性のある個人開発アプリが一斉にリジェクト | 楽しくiPhoneライフ!SBAPP

Appleのガイドラインだとこちらですね。
5.3 賭博ゲーム、ギャンブル、宝くじ/ロト

5.3 賭博ゲーム、ギャンブル、宝くじ/ロト

ギャンブル、賭博ゲーム、宝くじ/ロトは管理が複雑であり、App Storeでもっとも規制が厳しい分野の1つです。アプリケーションを提供するすべての地域におけるあらゆる法的義務を確認した後、こうした機能を搭載してください。この場合、審査には通常よりも時間がかかります。以下の点に注意してください。

5.3.1 抽選やコンテストの主催者は、アプリケーションのデベロッパである必要があります。
5.3.2 抽選、コンテスト、チャリティーくじの公式ルールをアプリケーションで提示し、Appleは主催者ではなく、いかなる形でも関わりがないことを明記する必要があります。
5.3.3現実のお金を使用するあらゆる形式の賭博ゲームで、ゲームのクレジットや通貨の購入にApp内課金を使用することはできません。また、アプリケーション内で抽選やチャリティーくじの購入、資金の振替を可能にすることは許可されません。
5.3.4 現実のお金を使用する賭博ゲーム(スポーツ賭博、ポーカー、カジノゲーム、競馬など)または宝くじ/ロトを提供するアプリケーションは、アプリケーションが利用される地域で必要なライセンスおよび許可を取得し、アプリケーションの利用をその地域のみに制限し、App Storeで無料配信する必要があります。カードカウンターなどの違法なギャンブルツールは、App Storeで許可されません。ロトアプリケーションには、考慮、機会、賞品の3つの要素が必要になります。

お金をかけてするギャンブルじゃなくて、縁日やイベント用の抽選アプリと行っても通用しなさそうですね。
諦めるしか無いかな〜。
うじゃうじゃ。/(^o^)\

【App Store】ガイドライン 4.3 SPAM

え〜、3年前から公開しているアプリが突然非公開にされました。

メールの本文はこんな感じ。

Hello,

We are writing to let you know about new information regarding your app currently live on the App Store.

Upon re-evaluation, we found that your app is not in compliance with the App Store Review Guidelines. Specifically, we found:

Design – 4.3
This app duplicates the content and functionality of other apps submitted by you or another developer to the App Store, which is considered a form of spam.

For this reason, your app will be removed from sale on the App Store at this time.

Deliberate disregard of the App Store Review Guidelines and attempts to deceive users or undermine the review process are unacceptable and is a direct violation Section 3.2(f) of the Apple Developer Program License Agreement. Continuing to violate the Terms & Conditions of the Apple Developer Program will result in the termination of your account, as well as any related or linked accounts, and the removal of all your associated apps from the App Store.

If you have any questions about this information, please reply to this message to let us know.

Best regards,

App Store Review

翻訳すると、

こんにちは、

現在App Storeに登録されているあなたのアプリに関する新しい情報をお知らせします。

再評価の結果、あなたのアプリはApp Storeレビューガイドラインに準拠していないことが判明しました。具体的には、

デザイン – 4.3
このアプリは、あなたや他の開発者がApp Storeに提出した他のアプリのコンテンツや機能を複製します。これは迷惑メールの一種です。

このため、この時点であなたのアプリはApp Storeで販売されなくなります。

App Storeレビューガイドラインの意図的な無視、ユーザーの欺瞞またはレビュープロセスの悪化は容認できず、アップルデベロッパープログラムライセンス契約の第3.2条(f)に直接違反しています。引き続きApple Developer Programの利用規約に違反した場合、アカウントや関連アカウント、リンクされたアカウントの削除、関連するすべてのアプリケーションのApp Storeからの削除が行われます。

この情報に関するご質問がある場合は、このメッセージに返信してお知らせください。

宜しくお願いします、

App Storeレビュー

画面右にリンクのある「ガラポン抽選機の代わりに催事用スロット」ってのがそうなんですけどね。
まだ課金がよくわからない時に作ったアプリで、機能制限したお試し用の無料版と、機能制限のない有料版の2つに分けてリリースしてるのがダメらしい。

Appleのガイドラインだとここだね。
4.3 スパム

4.3 スパム

同一のアプリケーションに対して複数のバンドルIDを作成しないでください。特定の場所、スポーツチーム、大学などに向けた異なるバージョンが存在するアプリケーションの場合は、単一のアプリケーションを提出し、異なるバージョンはApp内課金で提供する方法を検討してください。また、すでに飽和状態のカテゴリにアプリケーションを追加することは避けてください。App Storeには、おなら、げっぷ、懐中電灯、カーマ・スートラといったアプリケーションが多数あります。App Storeでスパム行為をすると、Developer Programから除名される可能性があります。

とりあえず「有料版だけ残すわー」って返事書いたら予想外の返事が。
それは次の投稿で。/(^o^)\

【Swift4】【Objective-c】SKStoreReviewController でアプリ内レビュー

最近流行りのアプリの中でレビュー(アプリの評価)をつけてもらうやつを調べてみた。

参考サイト
SKStoreReviewController を単純な条件で出すだけでも好意的なレビューが増えて良かった
SKStoreReviewController で App Store の評価数が急増した話 – wootan’s diary

機能としてはiOS10.3以降が対応のようです。
表示されるのは年に3回まで。
有意の時点で呼び出して、年に3回に達していないと表示されるらしい。
つまり、何回起動したときとか、そういう条件をつけて、レビューの請求をされてもおかしくない、
できれば好レビューが貰えそうな時に表示されるようにするのが良いっぽい。

コードとしてはStoreキットをインポートして使う。

Swiftの場合。

objective-cの場合。

一度この表示が出て評価を送信すると、その後は出なくなるのか、それとも、直後でも呼び出されるとまた表示されてしまうのか、そのへんの詳しい挙動がわからんのでそれなりの対応が必要そうです。

と、ゆーことで、いま手入れしてるobjective-c用にコードを書いてみた。

最初は10回呼ばれたら、その後は100回呼ばれる毎にレビューが請求されます。

あ、バージョンでの切り分けはこちらを参考にしました。
Objective-C で OS バージョン判定を簡潔に行う方法