2019年11月29日金曜日

Blenderで3Dモデルを作ってXcodeで使う

無料だけど高機能な3DアプリのBlender。ARなんかで表示させるモデルを作りたくて勉強してる。

細かい使い方、作り方はともかく、Xcodeに取り込んで使う旨で引っかかった点、気づいた点を書く。

2019年11月27日水曜日

Xcodeアップデート時のトラブル(ファイルが消えない)

Xcode11.0がリリースされた時だったと思うんだけど、Xcode10.xからの自動アップデートが途中で止まってしまう現象に悩まされた。
Xcode10.xを削除してから新規で11.0をインストールするといいと聞き、ゴミ箱を空にしようとしたものの、Xcodeが使用中だから空にできないとつれないお返事。

Xcodeのパッケージを開き、中のファイルを少しずつ消していったところ、かなり深い改葬にあった
GameCenterUIService.app
というアプリが悪さしていることがわかり、これだけを取り出したところ、他のXcodeのファイルは全て空にでき、Xcode11.0は無事インストールできた。

しかし、このファイルだけがどうしても消せない。
このアプリのパッケージを開くと、
ca.lproj
というフォルダの中に
InfoPlist.strings
があるだけ。
中身は
bplist00— _ CFBundleDisplayNameo Servei d UI del Game
  Center
  ! Z
とだけ書かれてる。

ちなみにファイル名をコピーしようとするとなぜか勝手に「InfoPliót.strings」に名前が変わり、「名前を変更しようとしています。」というパスワードを求めるダイアログが出ることがある。これもわけがわからない。

ca.projフォルダからInfoPlist.stringsを取り出して捨てようとしても、
いくつかの必要な項目が見つからなかったため、操作を完了できません。
(エラーコード-43)
と出てゴミ箱にすら入れられない。
別のフォルダに移動させようとするとコピーされる。(コピーされたものは捨てられる)

macOS 10.15 Catalinaをセーフブートして試してもダメ。
今のところゴミ箱が空にできないだけでさしたる問題はないが、解消されてもいない。

結局クリーンインストールで解決

このためにやったわけじゃないんだけど、システムがかなり不安定だったんでクリーンインストールしたら、さすがにゴミ箱を空にできた。
お疲れ様でした。ちゃんちゃん。

2019年10月10日木曜日

ダークモードの回避

左が正常なのに、ダークモードだと右の表示になる
Labelの文字が白くなり、TextViewの背景が真っ黒に

iOS13とXcode11、macOS 10.15 Catalinaにした後にアプリを審査に出したら、表示が見づらいからってリジェクトされた。
なんじゃこりゃ、TextViewの背景色なんていじった覚えないぞ!? と思ったが、iOS13から付けられた(余計な)機能、ダークモードのせいだった。
どうやら新しく提出したアプリから影響するらしい。

UISegmentedControlの色もこのとおり

回避方法


Info.plistのUser Interface Style を Light にすればアプリ丸ごとこれまでのライトモードで動いてくれる。
親方様(アップル)としてはダークモードへの対応を推奨してるんだろうけど、また今度ね!
しかしどうしてこう、いちいちデベロッパーに無理な負担を強いるかなあ…。

2019年10月2日水曜日

ARAnchorの追加と削除

以下はARKit3とSpriteNodeで作る、XcodeのARのテンプレート(AR空間にインベーダー👾の絵文字スプライトを表示させるやつ)を基に直したもの。

ARAnchorの追加

Scene.swiftの方でARAnchorの位置を決めて
sceneView.session.add(anchor: )
すると、ViewControllerのARSKViewDelegateメソッド
view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode?
が呼ばれるので、そこで貼りたいSpriteNodeをreturnしてやると、それがAnchorに貼られるという変則的なやり方になっている。
実際にどうやってanchorにspriteを貼ってるのかは知らない。

Scene.swift

//カメラ前方の位置にSpriteを表示するためのanchorを貼る
func addAlienAnchor(sceneView: ARSKView) -> Void {
if let currentFrame = sceneView.session.currentFrame {
var translation = matrix_identity_float4x4 //世界座標と向きを表す4*4の行列
//前方の多少ランダムな位置を決定
//行列の3列目のz値に-0.4なら前方0.4m
let x:Float = 0
let y:Float = 0
let z:Float = -4
translation.columns.3.x = x
translation.columns.3.y = y
translation.columns.3.z = z
//カメラの向いてる方向に対しての表示位置を計算
let transform = simd_mul(currentFrame.camera.transform, translation)
//セッションに新しいARアンカーを追加
let anchor = ARAnchor(transform: transform)
sceneView.session.add(anchor: anchor) //sceneViewのsessionにアンカー追加
//アンカー追加によってViewControllerのdelegateが呼ばれる
}
}

ViewController.swift

引数anchorがこれからspriteを貼るanchor。

func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
//省略するが、ここにAnchorに貼りたいSpriteNodeを作り、returnで返す
return spriteNode
}

ARAnchorの削除

新たなARAnchorを貼るとき、または貼るSpriteNodeを作った時、anchorを管理用の変数に入れておき、削除が必要になったらそれを削除すると、それに貼り付いているSpriteNodeもろとも削除される。
sceneView.session.remove(anchor: anchor)

貼る時も削除する時も、sceneView.sessionに対してのメソッドを使ってるわけだ。

ARKitのカメラの露出を変えたい(今は無理っぽい)

以下は最新のiOS13、ARKit3でのお話。今後のことは知らん。

やりたいこと

夜の外とか暗いところでARKitで撮影すると、普通のカメラ撮影に比べてやたら暗いので、露出がコードから変えられないものか。

調べる

最初に、今のところ調べた結果ではカメラの撮影設定(オートフォーカスとかも)をいじれるAPIは公開されていないようだ。

明るい所ではシャッター速度を変えて露出を調節しているようだが(絞りまで変えているかは知らない)、暗い所ではスローシャッターの限界が1/60秒みたい。
ちなみにARカメラのシャッター速度は以下のコードでわかる。

if let currentFrame = sceneView.session.currentFrame {
let 露光時間 = 1 / currentFrame.camera.exposureDuration
print("露光時間 1/\(露光時間)")
}

たとえば晴れた昼間カーテンをした部屋の中だと1/60や1/90、青空だと1/4484、太陽に向けると1/10000。暗い押入れに向けた場合1/60だった。
あんまりスローシャッターにすると手ぶれで物体の検出に影響するから制限してるっぽい? ISO感度も変更しない?

結論

今は無理っぽい。
あんまり暗い場所での使用は推奨されないんだろうな。ARanchorにSprite貼って表示させても、距離感が狂うせいか勝手に大きさが変わったり、消えちゃうことも。
暗闇に浮かぶ宇宙人や幽霊を表現したいんだが、別のやり方考えなきゃダメか?

2019年9月28日土曜日

バージョン表記にご注意

以前リリースしたものが些細なバグを治したものだったのでVersion 1.01だったのね。
んで、今度リリースするのを1.1にしてXcodeからvalidateかけたらエラーが出やがった。Invalid Bundleだって。前のよりも高い数字を入れろっていう。

前のが1.0.1のつもりだったんで、1.1ならいいだろうと思ったんだけど、よく考えたら1.01と1.1じゃ数学的には同じだな。AppStoreConnectでは単なる文字列としてじゃなく数字として見てるみたい。
一応公式にはメジャーバージョン・マイナーバージョン・些細な修正みたいな感じで数字を作れって推奨してるようだ。1.2.10みたいに。

AppStoreConnectじゃもうversion1.1として新バージョンを作り始めちゃってて、それを消したりバージョンを変えたり変更ができない。
しょうがないからXcodeのプロジェクトのVersionを1.1.1にしたらvalidateもuploadも通って、一応審査には出せた。
最終的に審査でリジェクトされるかもしれないけど、様子見。

もし1.01と1.1を本当に同じものとして見てるなら、1.1でBuildナンバーを1.01の時より増やせば行けるかもしれない。もしリジェクトされたら試すー。

って言うか、誤った情報の取り消しや編集をさせろよ…💢

2019年9月26日木曜日

iOS13はモーダル画面表示が変更された


iOS13はモーダル画面を表示する際、全面を覆うのではなく上の一部に隙間を残し、指で下にスライドすると画面が閉じるような仕様になった。
これは強化されたマルチタスクを扱う際の変更じゃないかと思うんだが、デフォルトがこれなので、iOS13 & Xcode11であらためてビルドすると今までのアプリもそうなってしまうようで困る。

直し方は簡単で、vcに遷移先のViewControllerが入っているとすると、以下のようにプロパティ modalPresentationStyle.fullScreen を指定するだけでいい。

vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)

簡単はいいけど、これをデフォルトにしなくてもいいじゃねえかって思うんだけどね。よけいな作業増やしやがって。

iOS13でAVAudioPlayerが落ちるようになった

以下のようなコードでBGMやSEを鳴らすアプリをリリースしてたのだが、iOS13にアップデートしたら音を鳴らす所で落ちるようになってしまった。
もっと詳細には try player = AVAudioPlayer(contentsOf: url) 
Thread 1: EXC_BAD_ACCESS (code=1, address=0x48) - broken with 
というエラーコードで落ちた。リリースしていたアプリが落ちるのだから、iOS13のせいだ。

import UIKit
import AVFoundation

class ViewController: UIViewController {
var player = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
do {
if let audioPath = Bundle.main.path(forResource: "BGM", ofType: "mp3") {
let url = URL(fileURLWithPath: audioPath)
try player = AVAudioPlayer(contentsOf: url)
}
} catch {
print("ERROR")
}
self.player.play()
}
}

調べたところ、頭でインスタンス変数として宣言している
var player = AVAudioPlayer()
var player:AVAudioPlayer!
とoptionalにしたところ、落ちなくなった。

変数作る際に初期化コードを書いても初期化されなくなる仕様変更があったんだろうか? そうなるとAVAudioPlayer以外でも同じ問題出てくる?

参考サイト


2019年9月22日日曜日

Xcode11リリース

2019/9/20にiPhone用にiOS13が、1日遅れの顰蹙でXcode11がそれぞれリリースされた。
iPadの方は新しくiPadOSになるということで、リリースはもうちょっと後らしい。
iOS13はダークモードがある以外は見た目にはあまり変化がない。

以下、とりあえず気づいた点だけ。

デバイス欄にiPhone、iPadに加え、Macが!


iPadOSとmacOSで共通のアプリを作れるような話もあるが、まさかmacOS 10.15 Catalinaにしたら一本のコードでiPhone、iPad、Macで共通のアプリなんて作れたりする?
それとも表示されてるだけで、iPadOSかmacOS用のテンプレートじゃなきゃここがenableにならんか?

SwiftUI

これまでのAutoLayoutのStoryboardとプロジェクトを作る段階で選択になる。
作成時、User Interfaceのメニューで選択

ひな形からプロジェクトを作成するとこれまでのViewControllerの代わりにSceneDelegate.swift、ContentView.swiftというファイルが作られている。

SceneDelegateはUIWindowSceneの状態が変化した時のdelegateメソッドが並んでる。これがUIViewControllerのviewDidLoadとかの代わりになるのかはよくわからん。

ContentViewの方が実際に画面デザインのコードを記述するファイルとなるようだ。
中に書かれたContentView構造体はSwiftUI用のviewプロトコルを継承した構造体の定義になっている。まだよくわかんないけど、ここに書くってことさえ覚えときゃいいか。

SwiftUIを勉強しようとしたのだが、コードと1対1のプレビューが出てこない。これMacもCatalinaに上げないといけないんだって(今はβだけ)。リリースまでおあずけ。コードを試すだけしかない。

単にAutoLayoutのconstraints設定を新しくするようなものでなく、UI部品の配置までコードとともに見えるようになるわけだな? ActionやOutletの接続はどうなるのやら。プレビューが見られるようになった場合、segueで繋がれたViewController同士の関係性とか見られるのかね?
Storyboardと併用できないようなので、早めに覚えてしまいたい。
詳しいことがわかったら勉強がてら別にまとめる。

ボタンアイコンを大量に搭載


Storyboardで右上の「+」ボタン(UI部品を選ぶ所)を押すとボタンなどのアイコンデザインが大量に出てくる。今までほんの少ししか搭載されておらず、あとは自作するしかなかったシステムアイコンだが、ようやくこれで統一が図れる。
StoryboardにドラッグするとImageViewとして貼られる。名前を指定すればコード中からも使える。

Swift UIを選択した場合は「+」ボタンの中にこの一覧がないんだが、別に見られるのかしら? まあ、UIButtonとかのImage名を入れるとこのメニューに名前が出てくるけどね。
アイコン画像サイズは最小しかない?

RealityKit

ARのテンプレートにRealityKitというContent Technologyが選択できるようになった。
RealityComposerというXcode内のアプリを使ってARに表示する物を編集できるようなのだが、まだよくわからない。
テンプレートをそのままRunするとタッチした正面に3Dの立方体を1個表示するアプリができる。
Composerでその質感とかを変えられるようなのだが、変えるとエラーが出るのでよくわからん。

2019年9月17日火曜日

LaunchImage(スプラッシュ画面)の大きさは適切に

様々なサイズの画面に対応させるべく、StoryboardのAutoLayoutを設定していても、シミュレータや実機で画面上下が黒帯になってしまうことがある。
iPhone8とかじゃきれいに表示できたのに、iPhoneXじゃこのとおり
これはLaunchImage(スプラッシュ画面とも。要するに起動時に表示される画像)の設定が未対応のため。
これをLaunchScreen.storyboardできちんとAutoLayoutのConstraintsを設定してやればいい。
AutoLayout未対応の頃のアプリだとLaunchScreen.storyboardがないが、New FileのUser InterfaceにLaunch Screenがあるから、それを追加すればいい。
あとはTARGETS / General / App Icons and Launch Imagesの Launch Screen Fileを今作ったLaunchScreenにしてやる。

2019年8月20日火曜日

ギャンブルアプリのレーティングと、韓国でのアプリ販売について

2019/8/20にアップルからメールが来たので、日本語に要約しておく。(自分用なので、内容が正確とは限りません)

韓国で販売するアプリについて、より多くのアプリを利用できるようにした。
また子供への安全対策として、頻繁に強烈なギャンブルを模した内容のものは、2019年8月20日以降に全ての国と地域でR17レーティングになる。
以下の条件を一つ以上満たす場合、韓国のApp Storeでは19歳以上への販売となる。
8月20日以降、App Store Connectのゲーム格付けおよび管理委員会から格付け番号を入力する必要があり、アプリは今週後半に公開される。格付け番号を持ってない場合は、今すぐ申し込みむこと。→韓国の格付け番号取得のためのサイトへのリンクらしい
  • 年齢が17歳以上のカジノサブカテゴリのアプリ
  • 次のコンテンツの説明の少なくとも1つで頻繁/強烈が選択されたゲームまたはエンターテイメントカテゴリのアプリ:
  • 模擬ギャンブル
  • 性的なコンテンツまたはヌード
  • アルコール、タバコ、または薬物の使用または参照
  • リアルな暴力
評価分類番号を入力するには:
  1. App Store Connectにサインインします。
  2. 大韓民国の可用性の下にあるアプリ情報セクションで、評価分類番号を入力する。
  3. レビューのためにアプリを送信する。
よくわからんのだが、ギャンブルとかが世界的に17歳以上対象になり、韓国はさらに厳しく19歳以上になったということか?
韓国はゲームを販売するのにも許可(管理番号を取る?)が必要みたいな話もあるみたいだし、よくわからんのよね。

2019年8月8日木曜日

App-ads.txtってなんじゃ?(まだよくわからねえ)

GoogleのAdMobを広告サービスとしてアプリに組み込んでいるのだが、App-ads.txtのサポートを開始するというメールが来た。なんだそれは?

調べたところ、よくわからないのだが、アプリデベロッパー(自分のこと)のサイト(iOSのアプリなら、AppStoreにサポートサイトとして登録してるサイトのことのようだ)にアップするテキストファイルで、これによって広告が不正使用されることを防ぐらしい。
詐欺対策。表示された広告料がアプリデベロッパー以外に不正に横取りされてしまうのを防ぐ?
偽の広告枠が表示されることを防ぐ。
広告枠が広告事業者より認定されたものかどうか

DSPがアプリ内の広告枠に入札する際、デベロッパーのサイトを確認し、正式に認証されている広告事業者のみの入札を受け付ける…そうだ。わかんねえ。

アプリの広告の仕組みがよくわかってないんでさっぱりわからんのだが、要は怪しげで詐欺まがいな広告が表示されないよう、承認されてる広告事業者の情報を持ってるファイルっぽい。
広告料が横取りされないようにということだけど、たとえば「アプリがウィルスに感染してるよ! 駆除するならこの(怪しげな)アプリをダウンロードなう!」とかいうよくあるやつなんかも排除してくれるんだろうか?

Googleの説明じゃ、まず「IABが提供するAuthorized Sellers for Apps 仕様書にそってapp-ads.txtファイルを作れ」って書いてあるんだけど、仕様書が英語で、しかもなんだかわかんねえんだよ。

DSP(デマンドサイドプラットフォーム):よくわからんが、Googleとかが提供してるネット広告サービスのプラットフォームことか?
IAB(インタラクティブ・アドバタイジング・ブリュー/インタラクティブ広告協会):ネット広告とかの協会だろうな



とりあえず、今の所は絶対実装しなければ広告表示されないといった類のものではなく、「変な広告が出てせっかくの広告料を受け取れない」ことがあってもいいなら設定不要かもしれない。
ちょっと様子見る。

2019年6月26日水曜日

デバイスがロックされてると出て実機確認できない

Xcode cannot launch アプリ名 on 〇〇のPhone because the device is locked.

Xcode9になったあたりから、上記のようなメッセージが表示されて実機確認できないことが増えた。
iOSの設定 / 一般 / リセット / 位置情報とプライバシーをリセット してやり、デバイスを繋ぎ直すと治る。
しかし、MacのiTunesが起動して「このコンピュータを信頼しますか?」みたいなやり取りをすることになるし、その後もリセットされた内容についてアプリごとにいちいち「フォトライブラリにアクセスしようとしています。許可しますか?」「位置情報を利用しようとしています。許可しますか?」と再回答しなければならず、面倒くさい。

他のやり方として、Xcodeの Window / Devices and Simulators でConnectedにあるデバイスを右クリックし、Unpair Deviceし、再度つなぎ直すと、デバイスの方で「信頼しますか?」メッセージとかは出るけど、Macの方はこれ以上作業が必要ないので少し便利。

根本的な原因はXcodeのバグだろうから、アップルが治してくれないとどうしようもない。

2019年6月24日月曜日

Xcode10になったらFrameworkがnot foundになった

Swift3の時代に作ったソースを久しぶりにXcodeで開いたら、Bridging-Header.hで#importしてるTwitterKit3.4.0とOpenCVがnot foundと表示されるようになってしまった。
リリースしてるアプリだから当然動いてたし、この間いじった覚えもないため、原因としてはXcode10になったくらいしか心当たりがない。

かなり試行錯誤し、結局は プロジェクトの
TARGETS / Build Settings / Search Paths / Framework Search Paths
がおかしかったことがわかった。
読んで字のごとくFrameworkを検索するPathを書くところだが、

$(inherited)
$(PROJECT_DIR)
$(PROJECT_DIR)/Twitter-Kit-iOS

などとなっていたのを

$(inherited)
$(PROJECT_DIR)/Twitter-Kit-iOS
$(PROJECT_DIR)

と順番を入れ替えたところ治ってくれた。
外部Frameworkをプロジェクトにaddすると勝手に新しい pathを追加してくれるみたいなんだが、関係ないpathも消した。
そのディレクトリになければ順番に下に書かれたディレクトリまで検索してくれそうなもんだけど、うまくいかないようで。

なお、実際のフォルダの階層は以上のようになってる。

プロジェクトへのaddは以下のようにした。
アップル純正のが入ったFrameworksフォルダとかもあるけど、直下に入れろみたいな情報も見たのでその通りにしてみてる。

ところでビルドできない致命的エラーは消えたけど、以下のようなWarningが一個出て消えない。
/Users/ユーザ名/Dropbox/Develop/Swift開発/tukkomi/Twitter-Kit-iOS/TwitterCore.framework/Modules/module.private.modulemap:1:29: Private submodule 'TwitterCore.Private' in private module map, expected top-level module
エラー個所は
explicit module TwitterCore.Private {
}
とだけ書かれたところ。とりあえず動きゃいいか。

TwitterKitはもうサポートが終了されてしまったのでこれからはSwifterというのに乗り換えた方が良さそう。

2019年6月20日木曜日

Swift3のDispatch semaphore

同期処理や非同期処理などを制御する仕組み。
Objective-Cと書き方がだいぶ変わったみたいなんでまとめる。
まだよくわかってないんで、書きかけとする。

言葉の意味

dispatch = 使者や手紙などを送る
semaphore = 手旗信号

要するに処理待ちのカウンターみたいなもので、値がマイナスの間はスレッドが停止する。
希望の処理が完了したら値をプラスしてやり、それが0になったらスレッド再開。

書式

詳しくは公式サイトで。

semaphoreを作る

let semaphore = DispatchSemaphore(value: 0)

semaphoreを通知、または増やす


semaphore.signal()

semaphoreを待つ、または減らす


semaphore.wait()
_ = semaphore.wait(timeout: DispatchTime.distantFuture
semaphore.wait(wallTimeout: DispatchWallTime)

同期処理させたいコードを書くところ

DispatchQueue.global(qos: .background).async { ここ }

具体的書き方

  1. semaphoreを作る
  2. DispatchQueue.global(qos: ここ).async { }の引数に優先順位を書く。
  3. DispatchQueue.global(qos: .xxxxx).async { ここ }のクロージャ内に同期処理させたいコードを書く
  4. 処理が一件終了したらsemaphore.signal( )を実行して待ち行列を解消して次の処理に移る。
  5. クロージャの最後にどれくらい待つのかを書く(たとえば処理が終わるまでずっと(以前はFOREVERとかなんとか書いてたけど、今はdistantFuture(遠い未来)だそうだ)とか)

let semaphore = DispatchSemaphore(value: 0)

_ = semaphore.wait(timeout: DispatchTime.distantFuture)

非サポートのSwiftバージョンを上げる

数年前に作ったプロジェクトを久しぶりにXcode10で開いたらSwift3のコードだったようで、もうサポートしてないって言われちゃった。カレントバージョンはSwift5。
普通Swift5にコンバートしてくれるボタンが出るけど、もうそれすらサポートされてないようだ。
エラーとして示されるコードをいくつか直しても同じメッセージが出たままビルドができない。

たしかXcodeの設定でコードのSwiftのバージョンを記憶してるところあったと思って調べて直した。

場所はプロジェクトのトップ/TARGETS/Build Settings/Siwft Compiler - Language/Swift Language Version。
これで最新のバージョンを選んでやれば、コードはSwift5で書かれていることにされる。でも当然コードの書き換えをしてくれるわけじゃないので、出てきたエラーを一つ一つ直していく。
Swift3からだと、#selectorで指定する先のメソッドの頭に @objc を付けなきゃいけないとかが多かった。それくらいはエラーメッセージをクリックすると出る「Fix」ボタンでやってくれたけどね。

初期のSwiftは毎年のように細かい書き方が変更されてきたんで、困りますな。頭いい人たちが作ってるんだから、最初からもうちょっときっちり仕様を決めて欲しかったけど、もうしょうがねえ。

2019年6月8日土曜日

WWDC 2019

  • ユーザーインターフェースのフレームワークSwiftUI登場
    • 徐々にUIKitから置き換わるもののようで、iPhoneなどのプレビュー画面を隣に見ながら部品/コードを置いていき、それが即座にプレビュー/コードに反映される。
    • デモを見た感じではdelegateとかが複雑にからんでいたTableViewも、Listとしてかなり短いコードで実現していた。
    • これまでのStoryboardは徐々になくなるんだろうけど、すべてのUIをSwiftUIでいきなり置き換えられるのかしら? もちろん最新の各種OSじゃないとダメよね?
    • これまでSwiftは短期間でver5まで上げられ、仕様の変更にデベロッパは右往左往させられたけど、また6とかに上がるのかしら? 大きく変わるのは勘弁。
  • 各国語ローカライズが簡単に
    • 各国AppStore用のスクリーンショットも自動生成してくれるって。コリャ便利。
  • iPadのアプリがmacOSでも動くようになる(Project Catalyst)
    • iPadアプリをMacのネイティブアプリとして開発できるんだそうな
    • iPadOSとmacOS Catalinaという組み合わせなの?
    • これまではUIKitをmacOSで使えるようにするという話があったけど、UIKitとSwiftUIと両方なんだろうか?
    • iPhoneのアプリは動かない?
  • iPadOSが登場
    • 画面や操作をiPadに特化したもの。対応はiPad Air2以降なんで俺のがギリギリ対応。
    • これまでのiPhoneのアプリは使えるんだろうか?
    • 年間ライセンスにもiPadOSの項目が作られるという噂も。また別に12000円くらい取られるのはイヤでござるよ。Mac向けの開発にも通じるからってことだろうか? ただの噂で終わって欲しい。
  • macOS 10.15 Catalina
    • 2012年中期以降のMacに対応だって。うちのMac mini Late2012がこれもギリギリ対応! じゃあ来年〜再来年あたりにはMacとiPad両方買い換えないといけない?(ノД`)
  • iOS、iPadOSなどのベータ版を使用するには、macOSもベータ版にしなきゃいけないんだって。そんな個人で2つのデバイスをベータにはできんわな。

2019年6月5日水曜日

2ファクタ認証ってなんだ?

Apple Developerで2ファクタ認証ってのが必要になって、うまく設定できずに困ってる。
そもそも2ファクタ認証ってなんだよってことで調べてまとめる。

アップルサポートサイトの記述

2ファクタ認証とは何ですか?2ファクタ認証は、Apple IDの認証を二重化することでセキュリティを強化し、たとえパスワードが他人に漏れても、本人以外はアカウントにアクセスできないようにする認証方式です。パスワードに加えて、信頼できるデバイスか、SMSまたは音声通話で届けられる確認コードの利用を求めることで、アカウントを保護します。パスワードだけではアカウントにアクセスできないため、Apple IDと、Appleに保管されている個人情報のセキュリティが向上します。
これまでのパスワード入力の他に、Apple IDと結びついた別のMac、iOSデバイスやケータイなどに確認用コードを表示し(音声の場合もあり)、そのコードを入力させることでセキュリティを高めるってわけだな。
つまりIDとパスワードが盗まれても、それと結びついたデバイスに表示される確認用コードが得られなければ不正ができないということだ。
たしかに最近は何かするとiPhoneに4桁とか6桁とかの確認コードが表示されてそれを入力しなきゃならないケースが多い。

これまでの2ステップ確認とはなんじゃ?

2ファクタ認証前も同じようにiPhoneに確認コードが送られてきてたような気がするんだけど、違ったっけ?
アップルサポートサイトの記述によれば、信頼できるデバイスをApple IDに結びつける点は一緒だし、そこに確認用コードを表示して入力させる点も一緒だ。
アップルの内部的な処理は知らないが、結局ユーザのエクスペリエンスというか、表面上の違いはわからなかった。
もしわかったら追記する。

Developerアカウントに2ファクタ認証を設定

まず、個人用Apple IDとDeveloper用Apple IDは分けてある。
それはDeveloper Program参加時に「分けたほうがいい」といろんなサイトに書いてあったから。

2ファクタ認証が必須になるってよ

今年の初め頃、
アカウントの安全性を高めるため、2019年2月27日以降、デベロッパプログラムのAccount Holder(アカウントホルダー)がApple Developerアカウントおよび「Certificates, Identifiers & Profiles(証明書、ID、プロファイル)」にサインインするには、2ファクタ認証が必要になります。
と連絡が来てたのは知ってたけど、よくわかんないでほっといた。個人用IDの方は2ファクタ認証設定済みである。

証明書が切れるってよ

今度はその 「Certificates, Identifiers & Profiles(証明書、ID、プロファイル)の有効期限切れが迫ってるで」とメールが来たので、書いてあるリンクから更新しようとしたら、「Developer用 IDに2ファクタ認証を有効にしろ」と出て先に進めなくなった。
「詳しくは、サポートページ(英語)を参照」っていうんでクリックしたら日本語ページに飛んだ。フィッシング詐欺サイトかと不安になったけど、アドレスはまともなんで大丈夫だろう。
んで、そこの関連情報欄に「iCloudとApple Developerアカウントで、別々のApple IDを使用するにはどうしたらいいですか?」というズバリなことが書かれてたんで、Macでその通り試したんだが、途中から書いてある通りにならず断念。
具体的には以下の手順なのだが、3でつまずいてしまった。
  1. 「システム環境設定」>「iCloud」>「アカウントの詳細」>「セキュリティ」で、個人用Apple IDの2ファクタ認証を有効にします。
  2. Macの「システム環境設定」>「ユーザとグループ」で、デベロッパ用Apple IDで使用する新しいシステムアカウントを作成します。
  3. 「システム環境設定」>「iCloud」>「アカウントの詳細」>「セキュリティ」で、デベロッパ用の新しいシステムアカウントにサインインし、デベロッパ用Apple IDの2ファクタ認証を有効にします。←ここ! ここで新しいシステムアカウントのサインインが求められないの! よって、以下の処理はできなかった。
  4. 「システム環境設定」>「インターネットアカウント」>「iCloud」で、プライマリシステムアカウントにサインインし、Macにデベロッパ用Apple IDを追加します。
  5. これで、個人用とデベロッパ用のApple ID両方の確認コードをプライマリユーザーアカウントで受信できる設定になります。

2ファクタじゃなく、2ステップ入力を試す

WebでApple IDの情報にアクセスして2ファクタ認証を有効にするのかとも思ったが、「2ステップ認証」しか出て来ず、とりあえずそっちを有効にしてみようとしたら、「セキュリティ保護のため6月7日 xx時xx分xx秒までお待ちいただく必要があります」だとさ。今日が4日なので要するに丸3日も待たされる。なんなん?
サポートサイトによれば、「セキュリティ対策として、アカウント情報に重要な変更が行われば場合(パスワードのリセット、セキュリティ質問の設定など)は、設定を完了できないように待機期間を設けている」ようだ。そういえばセキュリティ質問忘れたんでリセットしたっけ。そのせいか。

ウェブのApple ID管理ページだと、「2ステップ確認 アップグレードは6月7日 xx:xx:xx以降に可能です」ってあるから、3日後以降に2ステップ確認→2ファクタ認証にアップグレードできるってことか?

新アカウントでも2ファクタ有効にできず


さっき作った新しいユーザアカウントでMacをログインしなおし、システム環境設定のiCloudから「2ファクタ認証」を設定しようとしても、できないって出て有効にできない。なんなん!?

ネットで調べても、
  • 2ステップ認証を切らないとダメ
  • 最初に2ステップ認証を設定しなきゃダメ
とか出てきて、よくわかんねえ。

3日間待った

ちょうど3日目にアップル様から「ご利用の Apple ID に 2 ステップ確認を設定できるようになりました。」ってメールが届いた。
そこからリンクされたApple ID管理のWebページでログイン(もちろん開発用アカで)して、アカウントページのセキュリティ項目にはすでに「2ファクタ認証にアップグレードする」とかなんとか書かれてるんで、そのボタンをクリック。
ところがそれでONになってくれるわけじゃなく、Macのシステム環境設定/iCloudでONにする方法が表示されるだけ。なんかだまされた気分。
しょうがないからシステム環境設定開き、iCloudでそのとおりにしたんだけど、iCloudが個人用アカでログインされてるから当然すでに2ファクタはONになってる。

アップルの方で表示された手順にはないけど、当然個人アカをサインアウトして開発アカでサインインするんだと思ってそうしたところ、サインインの段階で「2ファクタ認証にします」とか表示が出て、勝手にやってくれた。
そのかわり開発アカでのサインインは個人アカが有効になってるからそっちを無効にしてからみたいな表示が出た。開発アカの2ファクタ認証有効化だけが目的なので、これはこれでよし。個人アカを再度サインインさせておしまい。

セキュリティの強化はわかるけど、なんかいろいろめんどくさくなったよね。冒頭の開発用証明書の更新だって以前は毎年やる必要なかったのに。去年くらいからだよな?
手順が複雑だからこうしてブログとかにまとめておかないと忘れちゃう。

2019年4月30日火曜日

Music Libraryの音楽を鳴らす

MediaPlayer、AVPlayer、AVAudioPlayerと3種類方法があるようだ。
ミュージック.appのようなMPMediaPickerContorollerを使うことで曲を簡単に選択できる。

MediaPlayerを使う

簡単さから言えば一番簡単。
currentPlaybackRateプロパティがあるが、再生速度の変更がなぜかできない。原因不明。


import UIKit
import MediaPlayer //Frameworkをインストールしておくこと

class ViewController: UIViewController, MPMediaPickerControllerDelegate {
//再生を継続するためにインスタンス変数としてPlayerを用意
var player:MPMusicPlayerController!
override func viewDidLoad() {
super.viewDidLoad()
player = MPMusicPlayerController.applicationMusicPlayer
}

@IBAction func pickMusic(_ sender: Any) {
let picker = MPMediaPickerController()
picker.delegate = self
//曲の複数選択の有無
picker.allowsPickingMultipleItems = false
present(picker, animated: true, completion: nil)
}
//音楽が選択された時呼ばれるdelegate
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
player.setQueue(with: mediaItemCollection)
player.play() //曲の再生
//pickerを消す
dismiss(animated: true, completion: nil)
}
}

AVPlayerを使う

AVFoundationのimportが必要。
動画再生にも対応したclassのようだ。
ミュージックライブラリの曲のassetURLを取得する点がちょい面倒だが、簡単。
assetURLからPlayerを作るときはtry文が不要。
rateに負の数を入れれば逆再生もできる
再生位置の指定はseekメソッドで、引数はCMTimeなので面倒のようだ。

AVAudioPlayerを使う

AVFoundationのimportが必要。
AVPlayerのAudio(音声)特化class?
ミュージックライブラリの曲のassetURLを取得する点がちょい面倒だが、簡単。
assetURLからPlayerを作るときはtry文が必要。
rateに負の数を入れても逆再生はできない
再生位置の指定はcurrentTimeプロパティで簡単。単位は秒。公式の解説だと再生中は現在位置からのオフセット位置、停止中はplay()メソッド開始位置からのオフセット位置とあるが、どちらも変わらず、曲の先頭からのオフセット秒数みたい?

import UIKit
import MediaPlayer
import AVFoundation


class ViewController: UIViewController, MPMediaPickerControllerDelegate {
var player:AVAudioPlayer!

//音楽が選択された時呼ばれるdelegate
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
//選択された曲を取得
let items = mediaItemCollection.items
if items.isEmpty {
print("曲が選択されていない")
return
}
//先頭の一曲のassetURLを取得
let item = items[0]
if let url = item.assetURL {
do {
player = try AVAudioPlayer(contentsOf: url)
} catch {
print("曲が取得できなかった。DRMの関係?")
player = nil
return
}
//曲の再生
player.play()
} else {
print("assetURL取得できなかった")
}
//pickerを消す
dismiss(animated: true, completion: nil)
}
}

曲などの情報を得る

先のmediaPickerのdelegateの、mediaItemCollectionの要素に曲名、アーチスト名などの情報にプロパティとしてアクセスできるので、取り出すのは簡単。

//音楽が選択された時呼ばれるdelegate
func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
let items = mediaItemCollection.items
if items.isEmpty {
print("曲が選択されていない")
return
}
let musicTitle = items[0].title //曲タイトル
let musicArtist = items[0].artist //アーチスト名
let albumTitle = items[0].albumTitle //アルバムタイトル
let albunArtist = items[0].albumArtist //アルバムアーチスト名

let artWork = items[0].artwork //アートワーク
imageView.image = artWork?.image(at: imageView.bounds.size)

//以下略
}

注意点

どのやり方をやっても、info.plistの Privacy - Media Library Usage Description を設定しないと
present(picker, animated: true, completion: nil)
でpickerが表示されない。
最近の傾向としてそうなのはわかるんだけど、エラーメッセージとか一切出てくれなかった。
似たようなので Privacy - Music Usage Description というのがあるので、間違えないこと。

2019年3月30日土曜日

MMDの3DキャラをSceneKitに表示させたい

WindowsにMikuMikuDance(MMD)ってアプリがあって、3Dキャラをアニメーションで踊らせたりできるわけだが、そのキャラをiOSのSceneKitに表示してみたいと考えた。
特にARKitを使ってけものフレンズのサーバルちゃんとかを室内に表示させたり。

調べてわかったのが以下のやり方。
Blenderとadd-onがダウンロードできるアドレスは自分で調べてください。

  1. 3DソフトBlenderとadd-on機能を使って、MMDの.mmxファイルをiOSで扱える.daeフォーマットに変換。
  2. Xcodeプロダクトに変換したdaeファイルをAdd。
  3. ARKitのサンプルコードを使って表示。

1:.pmxファイルを.daeファイルに変換

Blenderとadd-onのプラグインをダウンロードし、以下のBlenderの設定フォルダにプラグインを入れる。
Macintosh HD⁩/ユーザ/(⁨ユーザ名)/ライブラリ/Application Support/Blender/(アプリのバージョン。たとえば2.79)/scripts/addons 

しかし、アプリ起動しただけじゃ設定フォルダが作られないらしい。File / UserPreferences... でウィンドウを開き、Save User Settingsを押すとできるようだ。それでもプラグインをしまうscriptsフォルダ以下ができないみたいなので、自作することになった。scripts、addonsと複数形なので間違えないように。

‎またそのフォルダに入れるのはblender_mmd_tools-masterフォルダ内のmmd_toolsフォルダ以下だけ。
BlenderのUser Preferencesウィンドウを開いてAdd-onsのObject:mmd-toolsにチェックを入れると、.mmxファイルのインポートができるようになる。

.daeにエクスポート

拡張子.daeは正式にはCOLLADAっていうんだね。
エクスポート時は対象となるオブジェクトを選択し、以上のようにいくつかボタンをチェックし(チェックを外すのも)、コンボボックスからレンダーを選んでから行う。

2:プロダクトに.daeファイルをAdd

.pmxファイルをインポートし.daeファイルにエクスポートしたら、それをXcodeのart.scnassetsフォルダにaddする。
.daeファイルだけでやっている人がいたのだが、それだけだと当然テクスチャーが表示されない。しょうがないのでテクスチャーその他を含んだフォルダごとaddした。
その状態でその.daeファイルを選択すると、ちょっと時間がかかるがXcode上に3Dキャラが表示される。
もしその中にrigidbodiesというカテゴリができていたら、いらないらしいので削除しちゃっていい。
表示はすごく拡大されて歪んでるので、scaleなどを調整してやらないといけない。

保存できない問題が

.scnファイルをいじった後、RunやSaveしようとすると
The document “serval.dae” could not be autosaved. Your changes will not be saved until the problem is resolved.
などと出てなぜか保存できないことがあった。

どうやらHomeフォルダ以下のPermissionがおかしくなってたらしく、以下の2つのサイトを参考にPermissionの修復をしたところ、無事に保存できるようになった。
Homeフォルダ以下全てのファイルを修復するようなので、結構時間はかかる。
https://forums.developer.apple.com/thread/109669#335313
https://support.apple.com/en-us/HT203538
うちの環境だけの問題かもしれない。
EditorメニューのConvert to SceneKit scene file format (.sce) を選んで.scnファイルに変換する。 

2019年3月26日火曜日

Swift5が出た

Xcode10.2が出て、Swiftが5になったので、気づいた点だけまとめる。
(ついでにiOS12.2になってmacOS 10.14.4もリリースされた)
他にも色々あると思うけど、難しい使い方しなきゃあんまり使わないのもあると思うので。気づいたら追記します。

気づいた変更点

#のリテラル

" "だけでなく、# #で囲うことで、\ なしで " などを文字列の中で扱える。
書き方によってはスッキリするってことかな?

let a = "new"
var str = #"Hello, "the" \#(a) world"#

結果は
Hello, "the" new world
になる。

isMultiple( )

これまでは%で余りを求めることである数の倍数かどうか調べていたが、今後は .isMultiple()関数 で置き換えることができる。
以下の2つの結果は同じ「割れる」になる。

let ans = 10
if ans % 2 == 0 {
print("割れる")
} else {
print("割れない")
}

if ans.isMultiple(of: 2) {
print("割れる")
} else {
print("割れない")
}

2019年2月25日月曜日

SpriteのuserDataの使い方

SpriteNodeのカスタムプロパティとしてuserData辞書がある。
使い方は普通の辞書と一緒だが、あらかじめ最初にNSMutableDictionaryとして初期化しておかないとダメ。
そうしないと値を入れたはずなのにnilを返してくるため、悩むことになる。
あと、いちいちoptionalとして?とか付けないといけないのはめんどうだな。

spriteNode.userData = NSMutableDictionary() //最初に初期化が必要!
spriteNode.userData?["nodeID"] = NSNumber(value: cardIndex)

2019年1月27日日曜日

AdMobのためにFirebaseインストール

AdMobではAnalytics的使い方しかできないみたいだけど(よくわかってない)、とりあえず使ってみることにした。

CocoaPodsを使う

CocoaPodsってのを使ってインストールした方が良いと、今までもAdMob SDKなどでもさんざん言われてたので、今度それを使ってインストールしてみることにしたが、当のCocoaPods自体インストールしてないので、まずはそれをしなけりゃいかん。

ターミナル使ってインストール

ターミナルからコマンドを打ってインストールするんだが、ほとんどコマンドラインはわかってないので、詳しいことは書かない。
実際、Googleのサイトに書かれた手順ではうまくいかないことがあり、一般の方の解説ブログを参考にインストールした。ありがたや。

Setupが長い

CocoaPodsをインストール後にsetupするんだけど、どうもGitHubから3GB近いファイルをダウンロードするので、数時間かかってしまった。その最中にパソコンがスリープしたら、再開してくれないみたいなんで最初からやり直しになったし(ノД`)
ダウンロード後、自動でセットアップ作業に入るのだが、これがまた長い。何をダウンロードして何をセットアップしてるのかわからんので不安だ。
そもそも3GBもあるのに、機能がライブラリのインストールを簡単にするだけじゃないよね? きっといっぱいおいしい機能があるんだろうけど、とりあえず考えないでおく。
setupが終わって、その後の手順にも従ってプロジェクトのディレクトリに移り、pod init をする。
ここまでにPodfile、Podfile.lockなるファイルも同じ階層に作られると思った。

Podfileを書き換える

途中、以下のように書いてあるもんだからターミナルで何度も pod 'Firebase/Core' って打ったものの、「そんなコマンドはない」とか出て悩んだんだけど、正解はPodfileの中にその行を追加するんだった。知らねえし!
で、この pod 'Firebase/〜' を書き換えたり追加すると、Firebaseの他の機能もインストールできるんだそうな。
インストールするポッドを追加します。次のようにして Podfile にポッドを含めます。
pod 'Firebase/Core'
pod 'Firebase/Core'を追加
そして pod install ってやり、Firebase/Coreの必要ファイルがプロジェクトにインストールする。

これからは.xcworkspaceで

ここまででプロジェクトのフォルダ内に アプリ名.xcworkspace というファイルが作られてると思う。今後は今までの アプリ名.xcodeproj にかわってこれを開いて編集をすることになるそうだ。
.xcodeproj も開けるけど、Firebase関係の書類がインストールされてないらしく赤字で表示される。
CocoaPodsの作業はここでおしまい。

googleのplistをインストール

サイトの手順に従い、AdMobのサイトからGoogleService-Info.plist ってのをダウンロードする。
これを普通にプロジェクト内にAddする。ちゃんとCopyもな。
その後、UIApplicationDelegate内にimportと設定のための一行を追加しておしまい。
あとはAppStoreに新バージョンとして再アップすると機能するようになるんだと。アクセス解析を行うわけだが、プライバシー関係の設定とかしなくて怒られないかしら?

2019年1月24日木曜日

Firebaseってなんだ?

What is Firebase?

アプリの広告にGoogleのAdMob使ってるんだけど、前からFirebaseとリンクしろって出てくる。
Google Analyticsの機能を使い、アプリのアクセス解析をやってくれるらしいんだが、はっきりわかってないんで調べる。

mBaas

FirebaseはGoogleが運営するmBaas(Mobile Backend as a Service/エムバース)。
mBaasとはスマホアプリ向けにバックエンド部分のサービスを担う機能で、以下のようなメリットがあるという。

  • サーバ構築不要
  • サーバ運営不要
  • 低コスト
  • 開発工数削減
  • セキュリティ
デメリットとして、アプリの根幹を任せることになるので、信頼性などはmBaasを提供している企業に左右される。

具体的な機能

  • ユーザの登録とユーザ情報の管理
    • 新規登録を促すことと管理
    • ユーザ間で情報のシェアもできる
  • メール通知、プッシュ通知
    • ユーザ同士での情報のやりとりが可能に
  • 位置情報サービスとの連携
    • 位置情報を使った特定ユーザへのサービス提供など
  • SNSとの連携
    • SNSアカウントでのログインができる

Firebaseの機能

  • インフラの管理不要
    • Analytics、Database、Notifications、Crash Reportingなどが使える
  • Googleのインフラが使える
    • アクセス量や負荷を気にしなくて済む
  • 連携するプロダクトを一つのコンソールで管理できる
    • 詳細な設定なしでも利用できる
    • データやインサイト(なんやろ?)の共有も可能
    • 全プロダクトに一つのダッシュボードからアクセスできる
  • 基本無料で、拡張で利用した情報に応じて料金が発生

具体的な機能

  • Firebase Authentication
    • 安全な認証システム
      • メールアドレス+パスワード
      • 電話認証
      • Google、Twitter、Facebook、GitHubなどのアカウントによる認証
    • ドロップインUI
    • 包括的セキュリティ
    • 10行程度のコードで実装可能
  • Cloud Storage
    • Google DriveみたいなCloud Storageを扱える。無料なら5GBまで。
  • Analytics、Crashlytics
    • アプリの使用状況とクラッシュ状況を管理
……その他、ML(機械学習)やデータベース機能など、いっぱい機能がある。
要するに、今までアプリごと、サービスごとに、どこどこのサーバを借りて、データベース機能使って、アプリの使用状況管理はこれで…、ユーザの認証管理はこれで…ってやってたものがFirebaseとして一現に機能が提供され、管理もできるというのだな。こりゃ便利。

いろいろすごそう、便利そうなんだけど、Googleのサービスってちょっと使い方がややこしいこともあるので、そこは気をつけて使いたい。

とりあえず「いったい何か?」はわかったのでここまで。

参考サイト