- 投稿日:2020-07-20T23:41:34+09:00
Swift日記(8日目)
今日やったこと
- 用語の勉強
FizzBuzzやった
FizzBuzz.swiftimport UIKit func printfizzbuzz(fizz_value:Int){ for i in 1...fizz_value{ if i % 15 == 0 { print("FizzBuzz") }else if i % 3 == 0 { print("Fizz") }else if i % 5 == 0 { print("Buzz") }else{ print(i) } } } printfizzbuzz(fizz_value: 100)クラス・関数・変数
- 関数
- 実行する命令のかたまり、のようなもの。中でいろんな処理をしてくれる
- 変数
- 様々なものを入れておく入れ物。中身を一定のルールで変えることができる。中身を変えることができない入れ物を定数という。
- クラス
- 関数と変数をまとめた集まり。
- クラスの中にある変数をプロパティ、関数をメソッドと呼ぶ。なぜぇ。。。
- クラスの中でプロパティやメソッドが働いてできあがった変数をインスタンスという。
変数一個に2種類も呼び方あるの納得いかねぇ。。。
- 投稿日:2020-07-20T19:55:33+09:00
【Swift】可変長引数の関数に配列を渡したい!ときのworkaround
結論
自前の関数なら同名の関数をoverloadできます。
// 配列を引数に取る関数側にロジックを実装する func greet(_ people: [String]) { print("Hello, \(people.joined(separator: ", "))!") } // 可変長引数を持つ関数側では、内部で配列を引数に取る関数を呼び出す func greet(_ people: String...) { greet(people) }言語仕様として、引数に渡すときに配列を展開することはできないので、フレームワーク内の可変長引数(例えば、printなど)の関数に配列を渡すのは現状は難しいようです。
参考
Passing an array to a function with variable number of args in Swift
- 投稿日:2020-07-20T19:15:04+09:00
【Swift】\()を使用せず、文字列と一緒に変数をコンソール出力する方法
コンソールに文字列と一緒に変数を出力したい際、下記のように「 \ (変数)」を使用する方が多いと思います。
var foodList = ["カレー", "ラーメン", "カツ丼"] print("食べ物: \(foodList)") //出力結果 食べ物: ["カレー", "ラーメン", "カツ丼"]実は下記のように、変数の前に「 , 」をつけるだけでもOKなんです。
「 \ ()」をタイプするよりも圧倒的に楽なのでオススメです。print("食べ物: ", foodList) //出力結果 食べ物: ["カレー", "ラーメン", "カツ丼"]
- 投稿日:2020-07-20T08:29:25+09:00
ディクショナリからタプルの配列を作成する
はじめに
- Swift には、連想配列的なデータ構造としてディクショナリがあります
- ディクショナリはデータの順序を保証しないので、そのままではテーブルビューやコレクションビューのデータソースとして利用しにくいです
- その場合は、タプルの配列に変換すると上手く行きます
検証環境
- Xcode 11.5
- Swift 5.2
利用する機能
sorted(by:)
- ディクショナリのメソッド
- 引数に渡した関数
by
がソート条件
- 関数
by
の引数
- 2 つのタプル(それぞれディクショナリの n 番目の要素と n + 1 番目の要素に対応)
- 関数
by
の戻り値
Bool
(false
なら並び替え)- 戻り値は
[(key: ディクショナリの key の型, value: ディクショナリの value の型)]
- つまり、ディクショナリとほぼ同じ構造を持った「タプルの配列」
コード例
- 以下はディクショナリ
[String: Int]
からタプルの配列[(key: String, value: Int)]
に変換する例ですSortedDictionary.playgroundimport Foundation var scores: [String: Int] = [ "Steve Yamada": 34, "Jeff Takeshita": 87, "Mickey Yoshida": 100, "Charly Kinoshita": 53, "Anna Saito": 19, "Robert Suzuki": 97, "Erick Kawakami": 32, "John Miyabe": 64, "Gregory Goto": 76 ] print(""" Ascending by key ======================== """) var sortedByNameAsc: [(key: String, value: Int)] = scores.sorted { $0.key < $1.key } sortedByNameAsc.forEach { print("\($0.key): \($0.value)") } print(""" Descending by key ======================== """) var sortedByNameDesc: [(key: String, value: Int)] = scores.sorted { $0.key > $1.key } sortedByNameDesc.forEach { print("\($0.key): \($0.value)") } print(""" Ascending by value ======================== """) var sortedByScoreAsc: [(key: String, value: Int)] = scores.sorted { $0.value < $1.value } sortedByScoreAsc.forEach { print("\($0.value): \($0.key)") } print(""" Descending by value ======================== """) var sortedByScoreDesc: [(key: String, value: Int)] = scores.sorted { $0.value > $1.value } sortedByScoreDesc.forEach { print("\($0.value): \($0.key)") }出力結果Ascending by key ======================== Anna Saito: 19 Charly Kinoshita: 53 Erick Kawakami: 32 Gregory Goto: 76 Jeff Takeshita: 87 John Miyabe: 64 Mickey Yoshida: 100 Robert Suzuki: 97 Steve Yamada: 34 Descending by key ======================== Steve Yamada: 34 Robert Suzuki: 97 Mickey Yoshida: 100 John Miyabe: 64 Jeff Takeshita: 87 Gregory Goto: 76 Erick Kawakami: 32 Charly Kinoshita: 53 Anna Saito: 19 Ascending by value ======================== 19: Anna Saito 32: Erick Kawakami 34: Steve Yamada 53: Charly Kinoshita 64: John Miyabe 76: Gregory Goto 87: Jeff Takeshita 97: Robert Suzuki 100: Mickey Yoshida Descending by value ======================== 100: Mickey Yoshida 97: Robert Suzuki 87: Jeff Takeshita 76: Gregory Goto 64: John Miyabe 53: Charly Kinoshita 34: Steve Yamada 32: Erick Kawakami 19: Anna Saitoまとめ
- 状況に応じたデータの形式変換をする方法を押さえておくと、いろいろ応用ができそうですね
- 今回のサンプルは GitHub: aokiplayer/swift-sandbox/SortedDictionary に置きました
- なお、この記事は私のブログ記事からの転載です
- 投稿日:2020-07-20T07:23:37+09:00
写経してみた(ARKit)
はじめに
前々から
ARKit
さわってみたいな〜と思いつつずっとさわってなかったんですが最近ずっと引きこもってて時間があるのでARKit
をさわってみました。
新しいことを習得するには守破離の精神からいって「守」つまり真似することが大事かなと思います。プログラミングでいうと写経ですね。ということで
ARKit
で写経してみました。環境
- Xcode 11.5
- Deployment Target 13.0
とりあえずAR表示
今まで
ARKit
を全くさわってなかったのでほぼ何もわからない状態です。。。とりあえず ARKitのサンプルコード集「ARKit-Sampler」 を参考に 3D モデルを表示してみました。
手順は下記
- SceneKit Catalog を追加
![]()
- 3D モデルを追加(参考サイトのサンプルのship追加)
- Info.plist に
Privacy - Camera Usage Description
追加
![]()
- IB上で
ARSCNView
追加(ViewController
に接続)
![]()
- ARKit.framework 追加(これがないとlink errorになった。。。)
![]()
ViewController
にコード記載
import UIKit import ARKit final class ViewController: UIViewController { @IBOutlet private weak var sceneView: ARSCNView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. sceneView.scene = SCNScene(named: "art.scnassets/ship/ship.scn")! let config = ARWorldTrackingConfiguration() sceneView.session.run(config) } }これだけで AR が実現できます
(もっと
AVCapture
とかでゴリゴリしないといけないと思ってました。。。)写経
とりあえず 3D モデルが簡単に表示できることはわかった。次に何やろうと考えたときに 3D 空間に般若心経を写経したい!と思い至りました!!
写経するのに必要なのは下記
- 文字を表示する
- 文字にフェードアニメーションを付ける
とりあえずこの2つができれば写経できるはず!
文字を表示する
こちら(ARKitのAR文字をキレイにした話)を参考に文字表示してみました。とりあえず文字表示は
SCNText
を使うみたい。
まるっとコピペですがこれで表示できるみたいです。//カメラの現在位置を取得する guard let camera = sceneView.pointOfView else { return } let textGeometry = SCNText(string: message, extrusionDepth: 0.8) textGeometry.firstMaterial?.diffuse.contents = UIColor(named: "ArizarARFontColor") textGeometry.font = UIFont(name: "HiraginoSans-W6", size: 100) let textNode = SCNNode(geometry: textGeometry) let position = SCNVector3(0,0.1,-0.1) textNode.position = camera.convertPosition(position, to: nil) //カメラの向きに合わせる textNode.eulerAngles = camera.eulerAngles //大きさ設定 textNode.scale = SCNVector3(0.0001,0.0001,0.001) sceneView.scene.rootNode.addChildNode(textNode)文字にフェードアニメーションを付ける
こちら(SceneKitのアニメーションサンプル集)を参考にアニメーションを付けてみました。アニメーションには
SCNAction
を使うみたい。fadeIn
っていうそれっぽいのがあったので使いました。textNode.opacity = 0.0 // 0にしておく let action = SCNAction.fadeIn(duration: 0.2) textNode.runAction(action)ちょっとひっかかったのが
fadeIn
はopacity
を 1.0 に変更してくれるやつなのでもともとのopacity
を下げとかないと何も起きません。全体の実装
import UIKit import ARKit import SceneKit final class ViewController: UIViewController { @IBOutlet private weak var sceneView: ARSCNView! private var texts = [ "仏説摩訶般若波羅蜜多心経", "観自在菩薩", "行深般若波羅蜜多時", "照見五蘊皆空", "度一切苦厄", "舎利子", "色不異空", "空不異色", "色即是空", "空即是色", "受想行識亦復如是", "舎利子", "是諸法空相", "不生不滅", "不垢不浄", "不増不減", "是故空中", "無色", "無受想行識", "無眼耳鼻舌身意", "無色声香味触法", "無眼界", "乃至無意識界", "無無明", "亦無無明尽", "乃至無老死", "亦無老死尽", "無苦集滅道", "無智亦無得", "以無所得故", "菩提薩埵", "依般若波羅蜜多故", "心無罣礙", "無罣礙故", "無有恐怖", "遠離一切顛倒夢想", "究竟涅槃", "三世諸仏", "依般若波羅蜜多故", "得阿耨多羅三藐三菩提", "故知般若波羅蜜多", "是大神呪", "是大明呪", "是無上呪", "是無等等呪", "能除一切苦", "真実不虚", "故説般若波羅蜜多呪", "即説呪日", "羯諦", "羯諦", "波羅羯諦", "波羅僧羯諦", "菩提薩婆訶", "般若心経" ] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. sceneView.scene = SCNScene() let config = ARWorldTrackingConfiguration() sceneView.session.run(config) } @IBAction private func start(_ sender: Any) { guard let camera = sceneView.pointOfView else { return } // カメラ中央手前に表示 let startPosition = camera.convertPosition(SCNVector3(0, 0, -0.5), to: nil) // 文字サイズたぶん3cm let textSize: Float = 0.03 var index = 0 var x = startPosition.x for text in texts { var y = startPosition.y for t in text { let textGeometry = makeSCNText(String(t)) let textNode = SCNNode(geometry: textGeometry) textNode.position = SCNVector3(x, y, startPosition.z) let scale = 1 / (textGeometry.boundingSphere.radius * 2) * textSize textNode.scale = SCNVector3(x:scale, y:scale, z:scale) textNode.opacity = 0.0 y -= (textSize + textSize/3) let action = makeFadeAnimation(index: index) textNode.runAction(action) sceneView.scene.rootNode.addChildNode(textNode) index += 1 } x -= (textSize + textSize/3) } } private func makeSCNText(_ text: String) -> SCNText { let textGeometry = SCNText(string: text, extrusionDepth: 0.2) textGeometry.firstMaterial?.diffuse.contents = UIColor.white textGeometry.font = .systemFont(ofSize: 1) return textGeometry } private func makeFadeAnimation(index: Int) -> SCNAction { let duration = 0.2 let waitAction = SCNAction.wait(duration: duration * Double(index)) let fadeAction = SCNAction.fadeIn(duration: duration) return SCNAction.sequence([waitAction, fadeAction]) } }課題
とりあえず動くものはできましたがまだどの Node をどれの Child にすべきかとかはよくわかってないです。。。
文字サイズを決めてるlet scale = 1 / (textGeometry.boundingSphere.radius * 2) * textSize
もいまいちなんでこれで計算できるのかわかってません「観」とか一部の文字がなぜか表示できませんでした。
おいおい勉強していこうと思います
さいごに
これをやるために般若心経についてちょっと調べました(2冊本読んだ
)がすべてのものは存在するようで存在しないものなんだとか。
みなさんも開発で仕様がコロコロ変わるのを経験したことがあると思いますがそういうときにイライラしてはいけません。仕様もまた存在するようで存在しないものなのです。そう、仕様もまた「空」なのですこれ
「写経」を自動化し、オートで功徳を積める仕組みを作ってみたのでございます。みたときからやりたかった
参考