- 投稿日:2019-05-30T23:15:58+09:00
UnityでARKit2 - 第二回 -
UnityでARアプリ開発をやってみたい 第二回
- 第一回: UnityでARKit2
- 第二回: 本記事
1. この記事でやること
前回の記事で、BitBucketから拝借してきたunity-arkit-pluginのREADMEをちゃんと読んでおこうという回です。記事にするほどのことでもないかもしれませんが、論文を読むときもまずはAbstractから読みますし、きっと大切なことが書いてあると思います。
2. READMEを読む
概要
- Unity-ARKit-PluginはiOSのARKitSDKをUnityで利用できるようにしたものです
- ARKitのいろんな機能がちゃんと使えます
- 多くのアプリがすでにこのプラグインを使ってAppStoreに公開されています
- Unity2017.4以降のバージョンで使ってね
- 細かい使い方はTUTORIAL読んでね
- Licenseも読んでね(まぁ、MITライセンスだし変なことしなければ自由にしてね)
- プルリク遠慮なく
動作要件
- Unity v.2017.4 以降
- XCode 10.0 と ARKit SDK
- ARKit対応のiOSデバイス
- iPhoneなら6S以降
- iPadなら2017年発売モデル以降
- iOS12 以降
ビルドしてみよう
これは第一回: UnityでARKit2でやったので割愛しますが、いろんなサンプルが用意されているので、ひととおり試してみるのもいいかもしれないですね。
ここでポイントはUnityARBuildPostprocessor.cs(Unity-Technologies-unity-arkit-plugin/Assets/UnityARKitPlugin/Plugins/iOS/UnityARKit/Editor/UnityARBuildPostprocessor.cs)がビルド時にもろもろのXCodeプロジェクトへの変換処理をしてくれているということ。このファイル、とても大事。正直言って中身見てもなんのことやらさっぱりなので、なんかすごいありがたいなーという気持ちだけ持っておけば大丈夫だと思います。大事なのは感謝の気持ち。API
なんかいっぱい書いてるー :D
DelegateとEventのメジャーどころのリストですね。
これは手を動かし始めないとなんとも言えないやつです。あとがき
第二回はREADMEを読んでみました。
読んでみてわかったことは、ちゃっちゃとTUTORIALやれってことです。
あとはまぁ、動作環境のチェックは必須ですよね。はい、では次回はTUTORIALやります。
今回はこのくらいで。
ではでは。
- 投稿日:2019-05-30T20:45:58+09:00
UIKitの基本について
初めまして!きゅうすけと申します!
iOSエンジニア卵の私が、自社の定例イベントの勉強会で学んだ基礎の部分をまとめたものです!
メモ感覚ではありますが、これ違うぞってことがあったらぜひ教えてくださいー!(● ˃̶͈̀ロ˂̶͈́)੭ꠥ⁾⁾UIKitの基本
UIkit
iOSで必要なライブラリを用意してくれる
iOSアプリの画面をレイアウトをするには必要不可欠import: UIkit
UIkitをViewControllerを使えるようにする
これをしないとやらないとBottunとかが使えないよく使う基本的なUIKit
UILabel:テキストを表示する
UIButton :ボタンのUIを提供する
UITextField:テキストを入力するフィールド
UIImageView:画像を表示する
UITableView:リスト表示などに使用
UICollectionView:タイル貼りのように複数列表示することができる
UIScrollView:画面のスクロールを管理する
UITextView:複数行、スクロール可能なテキストを表示する
UISwitch :ON/OFFすることができるUI
UIDatePicke:年月日を選択するメモ
書いてあるソースコードをcommand押しながらクリック
→ 定義している場所に飛ぶ
今回の勉強会ではUITableView、UICollectionView、UIScrollViewについて説明があったので、
この3つについても書いていきます。UITableView、UICollectionView、UIScrollView
TableView
└iPhoneの設定画面
・縦方向でしか表示できない List表示
AndroidはrecycleView (ListViewは非推奨)・「Plain」と「Grouped」の二種類がある
Grouped → iPhoneの設定画面
└セクションがグレーになる
Plain
└セクションはあるけど見えてない?・セクションヘッダーとセクションフッターがある
CollectionView
└ iPhoneのMUSIC、メルカリ・縦方向に加えて横方向にも表示することができる
・AndroidはConstraint Layout? (ListViewは非推奨らしい)
・セクションヘッダーとセクションフッターがあるScrollView
・電子書籍のように複数のページを送って表示させたい場合などに使用する講師の人からのアドバイス
「この画面はTableViewをを使って実装した方が良いな」
「こっちの画面はTableViewではなくCollectionViewを使って実装だな」
みたいなことが、アプリのデザインを見た時に判断・イメージができるようになると、アプリ開発をする際にとても役に立つらしい!TableViewとCollectionViewはどう判断して作っているか
TableView:cellのデザインが一緒 一覧の表示の場合
CollectionView:カード的なデザインまとめ
UIKitがどんなものかちゃんと知らない状態でswiftに触っていたので、
今回学べたことによりなぜ毎回一番上に書かれているかということがわかりました。
知らないで書くより知って書くのとでは大違いだなと実感しました!
TablwViewも、自分でサンプル作ってもっと仲良くなっていこうと思います!
- 投稿日:2019-05-30T19:16:49+09:00
iPhone、iPadで複雑な形状をした図形内のタッチイベントを簡単に取得する方法 〜CAShapeLayer編〜
現在開発中のアプリで矩形以外の複雑な形をした画像をのタッチイベントを取得する必要があり日本語、英語で軽く検索してみたが、”これだ!”という文献が探せなかったので共有しておきます。Playgroud環境下ですぐにお試しできます。
下準備 〜画像作成〜
最終的にCAShapeLayerのPath(CGPath)に代入するので、Illustrator, Sketch, Figmaなどでベクター画像を作り、PaintCodeなどでUIBezierPathに変換します。
またPocketSVGというライブラリを使えば、SVGファイルをCGPathとして取得できます。
今回はその生成物(UIBezierPath)を解りやすいようにコード内にハードコーディングしていますが、図形の形状が複雑になると長くなってコードの可読性が悪くなるので別ファイル化した方が良いでしょう。
下記はUIBezierPath(上記の生成物をコピー)をCGPathで返す単純なfunctionです。UIBezierPathfunc getPath() -> CGPath { //Start: Created by PaintCode let bezierPath = UIBezierPath() bezierPath.move(to: CGPoint(x: 13.08, y: 129.49)) bezierPath.addLine(to: CGPoint(x: 1.58, y: 117.99)) bezierPath.addLine(to: CGPoint(x: 14.58, y: 104.99)) bezierPath.addLine(to: CGPoint(x: 0.71, y: 91.11)) bezierPath.addLine(to: CGPoint(x: 27.71, y: 64.1)) bezierPath.addLine(to: CGPoint(x: 27.71, y: 53.7)) bezierPath.addLine(to: CGPoint(x: 49.97, y: 31.45)) bezierPath.addLine(to: CGPoint(x: 49.97, y: 23.61)) bezierPath.addLine(to: CGPoint(x: 73.08, y: 0.5)) bezierPath.addLine(to: CGPoint(x: 101.97, y: 0.5)) bezierPath.addLine(to: CGPoint(x: 110.6, y: 9.13)) bezierPath.addLine(to: CGPoint(x: 125.95, y: 9.13)) bezierPath.addLine(to: CGPoint(x: 155.8, y: 39.71)) bezierPath.addLine(to: CGPoint(x: 155.8, y: 52.35)) bezierPath.addLine(to: CGPoint(x: 138.37, y: 69.78)) bezierPath.addLine(to: CGPoint(x: 97.72, y: 29.13)) bezierPath.addLine(to: CGPoint(x: 61.51, y: 65.34)) bezierPath.addLine(to: CGPoint(x: 68.66, y: 72.49)) bezierPath.addLine(to: CGPoint(x: 33.66, y: 107.49)) bezierPath.addLine(to: CGPoint(x: 47.91, y: 121.74)) bezierPath.addLine(to: CGPoint(x: 40.16, y: 129.49)) bezierPath.addLine(to: CGPoint(x: 13.08, y: 129.49)) bezierPath.close() //END return bezierPath.cgPath }CAShapeLayerとは?
CAShapeLayerは名前からわかるようにCALayerのサブクラスで、UIBezierPathなどで作ったベクター画像を表示します。ベクター画像は通常のイメージと異なり拡大縮小してもボケたりジャギーが出たりすることがないので、@2xや@3xの画像を作成する必要がありません。またCAShapeLayerのプロパティでパスの線の形状、色、パス内の色などを変更することが可能で、その多くがアニメーション可能です。そのため、簡単にタップしたらアニメーション付きで、色が変わる、大きさが変わるなどの仕掛けを作ることができます。
CALayerはCAShapeLayerの他にも、CATextLayer、CAGradientLayer、CATiledLayer など数々の表示に関するサブクラスがあります。下記記事は英語ですが、それらがよくまとまっているので、一読をお勧めします。
CALayer Tutorial for iOS: Getting Startedベクター画像の表示
CAShapeLayerを使った画像の表示手順は、
1. CAShapeLayerのインスタンスを生成
2. そのインスタンスのpathプロパティに上記で作成したパス(CGPath)を代入。
shapeLayer.path = getPath()
3. インスタンスのプロパティで線種、線色、色などを設定(任意)
4. UIViewのlayerにaddSublayerメソッドを使って、上記のCAShapeLayerのインスタンスを追加
self.layer.addSublayer(shapeLayer)
今回は上記手順をfunction(setupView())にまとめ、UIViewのカスタムクラスのイニシャライザでコールしています。UIBezierPathprivate let shapeLayer = CAShapeLayer() override init(frame: CGRect) { super.init(frame: frame) setupView() } private func setupView() { shapeLayer.path = getPath() shapeLayer.fillColor = UIColor.white.cgColor shapeLayer.lineWidth = 2.0 shapeLayer.strokeColor = UIColor.blue.cgColor self.layer.addSublayer(shapeLayer) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let touch = touches.first let point = touch!.location(in: self) shapeLayer.fillColor = shapeLayer.path!.contains(point) ? UIColor.red.cgColor : UIColor.white.cgColor }タッチイベントの設定
さて、いよいよ本題のタッチイベントの設定です。今回はカスタムUIViewに画像を表示しているので、先ずはUIViewのtouchesBeganをオーバーライドしてUITouchからタッチしたポイントを取得しています。
let point = touch!.location(in: self)
その後、CGPathのcontainsメソッドでそのポイントがパス内にあるかどうか確認しています。shapeLayer.path!.contains(point)このメソッドは領域内であればtrueを、外ならfalseを返します。
この例では画像をタッチした場合は画像を赤に、外であれば画像を白に変更しています。VectorImageTouchEventoverride func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let touch = touches.first let point = touch!.location(in: self) shapeLayer.fillColor = shapeLayer.path!.contains(point) ? UIColor.red.cgColor : UIColor.white.cgColor }まとめ
知ってしまえばとても簡単です。CAShapeLayer素晴らしい。下記にコード全文を載せておきますので、Playgroudにコピー、実行すれば試せます。
TouchableVectorImageViewimport UIKit import PlaygroundSupport let v = UIViewController() PlaygroundPage.current.liveView = v class TouchableVectorImageView:UIView { private let shapeLayer = CAShapeLayer() override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupView() { shapeLayer.path = getPath() shapeLayer.fillColor = UIColor.white.cgColor shapeLayer.lineWidth = 2.0 shapeLayer.strokeColor = UIColor.blue.cgColor self.layer.addSublayer(shapeLayer) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let touch = touches.first let point = touch!.location(in: self) shapeLayer.fillColor = shapeLayer.path!.contains(point) ? UIColor.red.cgColor : UIColor.white.cgColor } } extension TouchableVectorImageView { func getPath() -> CGPath { //Start: Created by PaintCode let bezierPath = UIBezierPath() bezierPath.move(to: CGPoint(x: 13.08, y: 129.49)) bezierPath.addLine(to: CGPoint(x: 1.58, y: 117.99)) bezierPath.addLine(to: CGPoint(x: 14.58, y: 104.99)) bezierPath.addLine(to: CGPoint(x: 0.71, y: 91.11)) bezierPath.addLine(to: CGPoint(x: 27.71, y: 64.1)) bezierPath.addLine(to: CGPoint(x: 27.71, y: 53.7)) bezierPath.addLine(to: CGPoint(x: 49.97, y: 31.45)) bezierPath.addLine(to: CGPoint(x: 49.97, y: 23.61)) bezierPath.addLine(to: CGPoint(x: 73.08, y: 0.5)) bezierPath.addLine(to: CGPoint(x: 101.97, y: 0.5)) bezierPath.addLine(to: CGPoint(x: 110.6, y: 9.13)) bezierPath.addLine(to: CGPoint(x: 125.95, y: 9.13)) bezierPath.addLine(to: CGPoint(x: 155.8, y: 39.71)) bezierPath.addLine(to: CGPoint(x: 155.8, y: 52.35)) bezierPath.addLine(to: CGPoint(x: 138.37, y: 69.78)) bezierPath.addLine(to: CGPoint(x: 97.72, y: 29.13)) bezierPath.addLine(to: CGPoint(x: 61.51, y: 65.34)) bezierPath.addLine(to: CGPoint(x: 68.66, y: 72.49)) bezierPath.addLine(to: CGPoint(x: 33.66, y: 107.49)) bezierPath.addLine(to: CGPoint(x: 47.91, y: 121.74)) bezierPath.addLine(to: CGPoint(x: 40.16, y: 129.49)) bezierPath.addLine(to: CGPoint(x: 13.08, y: 129.49)) bezierPath.close() //END return bezierPath.cgPath } } v.view.addSubview(TouchableVectorImageView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))) v.view.backgroundColor = UIColor.gray
- 投稿日:2019-05-30T16:22:52+09:00
(オサーンの備忘録2019)iOSのプロジェクトのlinkerエラーでやった事まとめ
podのリンカーエラーででやった事まとめ
エラー内容
clang:-1: linker command failed with exit code 1 (use -v to see invocation)
- 当たり前だけど、「xxxx.xcworkspace」で開く
- 念の為 キレイキレイのコマンド pod install --repo-update
- 自分の環境では
The `プロジェクト名[Release]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods-プロジェクト名/Pods-プロジェクト名.release.xcconfig'. This can lead to problems with the CocoaPods installationが出てたので、OTHER_LDFLAGSに$(inherited)追加
4. Build Active Architecture Onlyをpodsとprojectで合わせる。(これ大事)
で、ビルドが通りました。それとprovisioningでエラーになっていたので。
PROVISIONING_PROFILEを削除しました。
- 投稿日:2019-05-30T14:29:39+09:00
Realmでenumを使うときメモ
結論
privateプロパティのときは@objcMembersを書いていても@objcを書かないとだめ
これでいけそうだけどだめで
@objcMembers class Phone: Object { dynamic var name = "" private dynamic var osTypeRawValue = "" // privateの場合は@objcMembersを書いてあってもこれじゃだめ var type: OSType { get { return OSType(rawValue: osTypeRawValue) ?? .undefind } set { osTypeRawValue = newValue.rawValue } } enum OSType: String { case ios case android case undefind } }こうするとOK
@objcMembers class Phone: Object { dynamic var name = "" @objc private dynamic var osTypeRawValue = "" // @objcを明示的につける var type: OSType { get { return OSType(rawValue: osTypeRawValue) ?? .undefind } set { osTypeRawValue = newValue.rawValue } } enum OSType: String { case ios case android case undefind } }こんな感じでenumが使える
let phone = Phone() phone.type = .ios
- 投稿日:2019-05-30T12:49:43+09:00
最速で使うFlutter(Ubuntu編)
概要
とりあえずFlutterを使ってみたい方向けのシンプルな解説です。
できること
- Flutterの導入
- Android端末上でのシミュレート
Flutter(フラッター)は、Googleによって開発されたフリーかつオープンソースのモバイルアプリケーションフレームワークである。(Wikipedia)
公式ドキュメントを参考にしています。
英語が出来る方は、公式のドキュメント(Get started)を見たほうが早いです。環境 :
ubuntu 18.04
AndroidStudio インストール済みシミュレートには、Androidの実機が必要です。買いましょう…
1.インストール
1-1.ダウンロード
公式サイトからダウンロードし、解凍しましょう。
https://flutter.dev/docs/get-started/install/linuxcd ~/development tar xf ~/Downloads/flutter_linux_v1.5.4-hotfix.2-stable.tar.xz1-2.pathを通します
export PATH="$PATH:$HOME/development/flutter/bin" source ~/.bashrc1-3.ネット環境が不安定な方は実行してください
通常は要らないです。
flutter precache1-4.依存関係の確認をします
flutter doctorlib32stdc++6とライセンスへの同意が必要です。以下のコマンドを実行してください。
sudo apt install lib32stdc++6 flutter doctor --android-licenses1-5.AndroidStudioの設定
Android Studioを起動し、Android Studio Setup Wizardを完了させてください。
1-6.Androidデバイスの設定
開発者向けオプションからUSBデバッグを有効にします。
以下のコマンドを実行し、デバイスが正しく接続されていることを確認してください。flutter devices2.エディタの設定
拡張機能/プラグインを追加する必要があります。
VScodの場合:拡張機能からFlutterを追加
AndroidStudioの場合:プラグインからFlutterとDartを追加3.アプリを作成しよう
今回はAndroidStudioを用います。
3.1 プロジェクトの作成
ファイル > 新規 > New flutter Project
Flutter Applicationを選択します。Flutter SDK pathを以下のように設定します。
/home/[user]/development/flutterRunをクリックし実行してみましょう。
できました。
3.2 ホットリロード
Flutterの特徴の一つでもあるホットリロードを試しましょう。
lib/main.dart を開きます。
92行目にある'You have pushed the button this many times'を以下のように変更しましょう。
'You have clicked the button this many times'このように即反映されます。
3.3 プロファイルの方法
*ホットリロードやデバッグモードとは併用出来ません。その分、滑らかに描画できます。
flutter run --profile4.アプリ作成のガイド
間違いがあったら教えてください><
最後まで、ありがとうございました。さようなら〜
- 投稿日:2019-05-30T01:14:41+09:00
Swift - init(repeating:count:)で配列を生成するときの注意点
基本的な使い方
// 4人で点数を競うときの初期値を0でいれておく var playerScores = Array(repeating: 0, count: 4) print(playerScores) // [0, 0, 0, 0] // 書くプレイヤーがスコアを獲得 playerScores[0] += 5 playerScores[1] += 10 playerScores[2] += 15 playerScores[3] += 20 print(playerScores) // [5, 10, 15, 20]クラスのインスタンスを格納する配列を生成する
class Player { var name = "" var score = 0 } var players = Array(repeating: Player(), count: 4) // 書くプレイヤーに名前を代入 players[0].name = "John" players[1].name = "Paul" players[2].name = "George" players[3].name = "Ringo" players.forEach { player in print(player.name) } /* Ringo Ringo Ringo Ringo みんなRingoになってしまった */クラスのような参照型の場合、同じ参照を持つインスタンスがrepeatingにより複数生成されてしまいます。例えば、上記のようにクラスのインスタンスを配列で格納し、セルに表示する情報を管理する場合などは、1つの要素の情報を変えると他の要素にまで影響があるので注意が必要です。
解決策
structなら値型なので上記のように1つの要素の値を変更すると、他の要素まで影響があるということはありません。
struct Player { var name = "" var score = 0 } var players = Array(repeating: Player(), count: 4) // 書くプレイヤーに名前を代入 players[0].name = "John" players[1].name = "Paul" players[2].name = "George" players[3].name = "Ringo" players.forEach { player in print(player.name) } /* John Paul George Ringo */



