macOSの環境設定のようなレイアウトはNSGridViewで実装する
MapKitとCoreLocationで現在地の地図を表示する
Xcode 9.2 / Swift 4.0.3
現在地情報はシミュレーターのデフォルト値を使用しています。
MapKit
地図を表示する
import UIKit import MapKit class ViewController: UIViewController { lazy var mapView: MKMapView = { let mapView = MKMapView(frame: view.frame) return mapView }() override func viewDidLoad() { super.viewDidLoad() view.addSubview(mapView) } }
CoreLocation
現在地を取得
info.plist
に権限設定を追加します。
Valueには使用用途を説明する文章を入力する必要があります。
ここに入力した文字列はユーザーに表示されます。
権限設定 | 説明 |
---|---|
NSLocationWhenInUseUsageDescription | 使用中のみ許可 |
NSLocationAlwaysAndWhenInUseUsageDescription | 常に許可、使用中のみ許可 |
NSLocationAlwaysUsageDescription | 常に許可 |
iOS11 から使用中のみ許可(NSLocationWhenInUseUsageDescription)
のサポートが必須となっているので上2つのどちらかを使うことになると思います。
使用中のみ許可と常に許可の両方をサポートして、それぞれ違う説明文を表示する場合だけNSLocationWhenInUseUsageDescription
とNSLocationAlwaysUsageDescription
を指定します。
import UIKit import MapKit import CoreLocation class ViewController: UIViewController { let locationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.delegate = self } } extension ViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { switch status { case .notDetermined: locationManager.requestWhenInUseAuthorization() case .authorizedWhenInUse: locationManager.startUpdatingLocation() default: break } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // locationsに現在地が入っています } }
MapKit + CoreLocation
現在地の地図を拡大して表示する
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let coordinate = locations.last?.coordinate { // 現在地を拡大して表示する let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01) let region = MKCoordinateRegion(center: coordinate, span: span) mapView.region = region } }
MKCoordinateSpan
に指定しているlatitudeDelta
/ latitudeDelta
の値を小さくするほど拡大されます。
地図上の現在地にピンをつける
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let coordinate = locations.last?.coordinate { // ピンをつける let pin = MKPointAnnotation() pin.coordinate = coordinate mapView.addAnnotation(pin) // 現在地を拡大して表示する let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01) let region = MKCoordinateRegion(center: coordinate, span: span) mapView.region = region } }
try! Swift 2018 Tokyoに参加しました | Day 2
try! Swift 2018 Tokyo 2日目のスライドなどのまとめ+企業ブースメモ
Expression Problem を解決する | Day 2-1
Swift もくもく会 in Barcelona | Day 2-2
Swift によるアルゴリズムの可視化 | Day 2-3
Kitura で Codable ルーティング | Day 2-4
-
超解像+CoreML+Swiftを使ってアプリの画像データ転送量削減に挑戦する | Day 2-5
漫画をサーバー側で低解像度化してクライアント側で高解像度化するお話。 OSSとして公開、残念ながらモデルは大人の事情で非公開だそうです。 モデルを作成するスクリプトは含まれているそうなので漫画の電子データを沢山もっていれば試せそうです。
iOSでCharlesを導入する | Day 2-6
Charles for iOS がレビュー中とのこと。無事リリースされて欲しいですね。
拡張現実における体験設計 | Day 2-7
現実とはこれまで取り組んで来た中で一番巨大なView Controllerである。
Swift エンジニアのための Kotlin 入門 | Day 2-8
Swift5のOwnershipに備える | Day 2-9
-
デジタル信号処理 in Swift | Day 2-10
Codableが導く型安全な世界 | Day 2-11
iOS / Swift における対話型インターフェースの作成 | Day 2-12
UIImageView vs Metal | Day 2-13
www.slideshare.net
GPUのことを考えるきっかけになるセッションでした。 ゲームを作っていたころは、ずっとGPUのこと考えてる状態でしたが最近はあまり考えてません。
- コマンドを送る時は1回にまとめる。
- テクスチャはGPUにキャッシュさせる。
などは、基本的にMetalだけでなくOpenGLやDirectXでも同じです。
Swiftが動くDockerコンテナの各OSの性能比較 | Day 2-14
型とパフォーマンスで見るType-erasureの利点 | Day 2-15
Make faces big by Vision and CoreGraphics | Day 2-16
-
開発者ツールと経験への時間投資 | Day 2-17
企業ブース
Yahoo! JAPANさんのペアプロ実演を見学しました。
作業の流れはざっくりこんな感じだったと思います。使用されてるタスク管理ツール名は忘れました。
- (ツール)タスクの確認
- コスト出し(1~3をじゃんけんみたいに指で同時に出して、食い違っていたら口頭ですり合わせしてからツールに記載)
- (ツール)該当タスクを開始状態にする
- ナビゲーターがテストを書く
- ドライバーが実装を書く
- テストをパスするまで頑張る
- コミット
- (ツール)該当タスクを完了状態にする
- (ツール)プロジェクトオーナーが該当タスクを承認する
ドライバー/ナビゲータで片方がユニットテストを書いて、もう片方が実装を書く形で進めてるとのことでした。
コードレビュー => ペアプロの作業内で確認してるので改めてレビューはしていない。ひとり作業が発生した場合は別途行う。
ドキュメントはない => メンバー全員で入れ替えながらペアプロですすめているから全員が同時にやめない限りどうにかなる
作業環境=>1台のMac + セカンドディスプレイ
Rx => 一時期使ってたが今は使っていない
書いてて思いましたが、スニペット/テンプレートやキーバインドなどなど個人間で異なるだろう環境設定をどうしてるのか気になります。
追記
そういえばテストをするたびにマウスカーソルを操作して個別にテストを選択されていました、
あそこはショートカットを使うとマウスカーソルを移動する必要がなくなります。
コマンド | ショートカット | 説明 |
---|---|---|
Test | ⌘⌥^ + U | カーソルがあるテストを実行 |
Test Again | ⌘⌥^ + G | 前回実行したテストを再実行 |
try! Swift 2018 Tokyoに参加しました | Day 1
try! Swift 2018 Tokyoに参加したので各セッションのスライドなどをまとめます。
2016, 2017に引き続き今年もniwatakoさんが聞き起こしをしてくださってるので細かいことはそちらを参照するといいと思います。
裏 Swift Tour | Day 1-1
SIL入門 | Day 1-2
My slides "SIL for First Time Learners" from try! Swift Tokyo 2018. https://t.co/SfPa23HI8ghttps://t.co/EjRrrBNdS0#tryswiftconf #swiftlang
— yusuke_kita (@kitasuke) 2018年3月1日
Clang モジュールの探検 | Day 1-3
Relative Pathsが使えないのくだりは私も困ってるので共感できました。
これができないのでKannaはPlaygroundが使えません。(libxml2のヘッダパスが解決できない)
レスポンダチェーンを知ろう | Day 1-4
-
関心の分離と単純化のためのSwiftコードの最適化 | Day 1-5
コーダーがデザインすべきなのか | Day 1-6
Event driven networking for Swift | Day 1-7
ノンブロッキングIOをSwiftで扱うお話。
セッションの最後にSwiftNIOがOSSとして公開されました。
KituraやVaporがSwiftNIOを活用するのか興味がありますね。
変性のダイヤモンド | Day 1-8
SwiftyPi | Day 1-9
Raspberry PiでSwiftを動かしたお話。
Swift 4はARMv7に対応していないのでSwift 3.1.1とのこと。
Swift 4での32bit CPUサポートは誰かが頑張らない限りされそうにないですね。
[SR-124] Port Swift to Linux x86 32-bit - Swift
我が家を支えるSwiftの技術 | Day 1-10
Swiftを使って家庭内で使用するアプリやWebサーバーを作ってるお話。
どうもWebサイトのパースに拙作のKannaも活用していただけてるようで、
お役に立てていれば嬉しいです。
(Swift 4に対応したリリースを出し忘れてることを思い出したので出しました)
UI Test の楽しさとメリット | Day 1-11
ブロックチェーンのクライアントをSwiftで実装する | Day 1-12
Protocol Oriented WebAPI Abstraction | Day 1-13
-
👾 | Day 1-14
XcodeはApple Watchに特化したゲーム開発ツール。
ゲームとRxは相性がいいのでRxSpriteKitを作ったそうです。
AST メタプログラミング | Day 1-15
個人的に今回のtry! Swiftで一番面白かったです。
iOSでAlureを使うための準備
こちらを参考にビルドします。私の環境では修正が必要な箇所が異なっていたのでメモ。
AlureをiOSシミュレーター向けにビルドする
- 公式からAlureをダウンロード
- https://github.com/cristeab/ios-cmake からCMakeのiOS用ツールチェインをダウンロード
- cmake
cmake . -DCMAKE_TOOLCHAIN_FILE=./ios-cmake/toolchain/iOS.cmake -DIOS_PLATFORM=SIMULATOR64
- CMakeCache.txt を修正
includeパス指定が;
で連結されている場所を(半角スペース)に置換する。
- make
make
libalure-static.a
を*.o
に展開
ar -x libalure-static.a
*.o
ファイルを全てXcodeプロジェクトに追加。
Alureを実機向けにビルドする
上記手順で作成されるライブラリはシミュレーター向け(x86_64アーキテクチャのみ対応)となっているため実機での実行ができません。 実機で実行できるようにするには実機向けにビルドする必要があります。
手順は同じでCMakeのオプション(最後の部分)を書き換えるだけです。
cmake . -DCMAKE_TOOLCHAIN_FILE=./ios-cmake/toolchain/iOS.cmake -DIOS_PLATFORM=IOS
今度は実機のアーキテクチャ(armv7/armv7s/arm64)にしか対応していないため、シミュレーターで実行できなくなります。
一度のビルドでarmv7/armv7s/arm64/x86_64全てに対応させるオプションは無いようなので シミュレーター向けと実機向けのライブラリを自分で統合します。
ユニバーサル対応する
lipoコマンドでシミュレーター向けライブラリと実機向けライブラリを統合してユニバーサルライブラリを作成します。
xcrun -sdk iphoneos lipo -create [実機向けライブラリ] [シミュレーター向けライブラリ] -output [出力パス]
全ての *.o
ファイルに対して上記コマンドを適用したら完了です。
出来上がったライブラリをXcodeプロジェクトに追加するとシミュレーター/実機の両方で実行できるようになります。
補足
iTunes Storeに申請する場合は、シミュレーター用ライブラリを除外する必要があるので注意が必要です。
Bitriseでオーディオ再生をテストする(iOS)
趣味で音楽プレーヤーアプリを作り始めたのでBitriseをセットアップしました。
初回テストを兼ねて最初にオーディオを再生する簡素なコードとテストを書いてCIを動かしたところテストが失敗しました。
(もちろんローカル環境でのテストはパスしている状態です。)
エラーログは下記の通り。
[AudioHAL_Client] AudioHardware.cpp:875:AudioObjectAddPropertyListenerBlock: AudioObjectAddPropertyListenerBlock: no object with given ID 0 [AudioHAL_Client] AudioHardware.cpp:875:AudioObjectAddPropertyListenerBlock: AudioObjectAddPropertyListenerBlock: no object with given ID 0 [DDAgg] DefaultDeviceAggregate.cpp:737:BuildAggregate: Error finding valid input or output devices! [AudioHAL_Client] AudioHardware.cpp:2682:AudioDeviceStop: AudioDeviceStop: no device with given ID [aqme] 318: error -66680 finding/initializing AQDefaultDevice [aurioc] 918: failed: -10851 (enable 2, outf< 2 ch, 44100 Hz, Int16, inter> inf< 2 ch, 0 Hz, Int16, inter>) [AudioHAL_Client] AudioHardware.cpp:2682:AudioDeviceStop: AudioDeviceStop: no device with given ID [aqme] 318: error -66680 finding/initializing AQDefaultDevice 108: * * * NULL AQIONode object 771: Can't make UISound Renderer
有効な入出力デバイスが見つからないと言っていますね。 Bitriseでオーディオ再生を伴うテストをする場合、audio input/output deviceを作る必要があるみたいです。
オーディオデバイスを作成する手順
Homebrewでインストールすることができます。
- Workflowに
Script
stepを追加 - Script contentを記入
#!/usr/bin/env bash set -ex brew install Caskroom/cask/soundflower brew install switchaudio-osx SwitchAudioSource -s "Soundflower (2ch)" -t input SwitchAudioSource -s "Soundflower (2ch)" -t output
この状態でリビルドすると失敗していたテストケースが全て成功するようになりました。
参考
macOS appのCloudKitでカスタムコンテナを使う時に気をつけること
環境:Xcode 8.3.3 / Swift 3.1
追記
デフォルトコンテナとカスタムコンテナが一致している場合はCKContainer.default()
が使えて、
一致していない場合はコンテナ名を指定する必要がある、、、ということでした。
問題
macOS appでCloudKitを使う際、Capabilitiesでカスタムコンテナを1つだけ指定してから
CKContainer.default()
でレコードを保存しようとすると下記エラーが出ました。
"Server Rejected Request" (15/2001); "Request failed with http status code 500"
コードはこんな感じです。
let database = CKContainer.default().privateCloudDatabase let record = CKRecord(recordType: "Memo") record.setValue("Hello!", forKey: "message") database.save(record) { _, _ in }
解決方法
どうやらmacOS appでカスタムコンテナを使う場合、
CKContainer
のインスタンスを作る時にコンテナ名を指定しないといけないようです。
let database = CKContainer(CUSTOM_CONTAINER_NAME).privateCloudDatabase
なお、iOSでカスタムコンテナを使う場合はCKContainer.default()
が問題なく使用できます。
勘違いでした。CKContainer.default()
だとCapabilitiesのカスタムコンテナの指定は無視され、
Use default containerを指定した場合と同じコンテナが使われます。
macOS appだとデフォルトコンテナが自動作成されないようで、そのためにエラーが発生していました。
リファレンス等で確認できませんでしたが、ハマったのでメモとして残しておきます。