- 投稿日:2020-10-15T22:13:02+09:00
Swiftでcosxの近似値を求める
なぜSwiftなの?
Swiftは環境構築などする必要がなく,MacかiPadがあればPlaygroundsをインストールするだけで使うことができる。
また,Playgroundsにはステップ実行やゆっくり実行という機能があり,for文やwhile分をステップごとに実行し,実行されている時の値の変化を確認することもできる。
さらに,ビューア機能を使えば変数の変化の様子を勝手にグラフ表示してくれる。
cosx のマクローリン展開
$cosx$をマクローリン展開すると,
$$
cosx=1-\frac{x^2}{2!}+\frac{x^4}{4!}-⋯+\frac{(-1)^nx^{2n}}{(2n)!}+⋯
$$
と表されるのであった。この記事では$sinx$の近似値をプログラミングを使って求めていく。(言語はSwift)ipadでも大丈夫。1.変数を用意する
マクローリン展開は何回でも微分できる関数$f(x)$を$x$の冪乗関数の級数の展開式の和で近似させるものであるのであった。この記事では$sinx$の値を
sum
として,sum
にだんだん値を加えていく。var sum = 0 print(sum) //0 sum += 1 print(sum) //1また,近似する$x$を入れる定数も用意しなければならない。この時近似する値として$\pi/6$や$\pi/3$などの値を用いたいので,$\pi$が使えるよう
import Foundation
を書いておく。import Foundation var sum = 0 let x = Double.pi/2さらに,項として更新され続ける変数を用意する。
var item = x第一項は定数と同じになるので,
x
を入れておく。最終的なコードは以下のようになる。
import Foundation var sum = 0.0 //int型とdouble型は足算できないので,0.0と書きdouble型にする。 let x = Double.pi/2 var item = x2.x=π/2として,第二項までコーディングする
コーディングをする上で小さな値から始めることや具体的な値で試行錯誤することは重要だと思う。(個人の見解)。この記事でもその理念に則り$x=\frac{\pi}{2}$として第二項まで,つまり
$$
cosx=1-\frac{x^2}{2!}
$$
までコーディングする。import Foundation var sum = 0.0 //int型とdouble型は足算できないので,0.0と書きdouble型にする。 let x = Double.pi/2 var item = 1 sum += 1 sum += -(x*x)/Double(2*1)
sum
に$1$を加え,次の行で$-\frac{x^2}{2!}$を加えている。最後に真値と比較する
import Foundation var sum = 0.0 //int型とdouble型は足算できないので,0.0と書きdouble型にする。 var x = Double.pi/2 sum += 1 sum += -(x*x*x)/Double(3*2*1) print(sum)//近似値0.9248322292886504 print(sin(Double.pi/2))//真値1.0
Double(2*1)
としているのはInt型をDoule型に変換しているのだが,この記事では本質的な部分ではないので説明は割愛。3.一般化しやすいように工夫する
さっきは第二項を$-\frac{x^2}{2!}$としたが,これでは項数が増えるたびに$x$を増やさなければならない。項数が増えても短くコーディングすることができるように工夫を加える。
import Foundation var sum = 0.0 //int型とdouble型は足算できないので,0.0と書きdouble型にする。 let x = Double.pi/3 var item = 1 sum += item for i in 1 ..< 3{ item *= -(x*x)/Double((2*i)*(2*i-1)) sum += item } print(sum)//近似値0.525479753410744 print(cos(Double.pi/3))//真値0.54.項数をふやす
一般化することによって項数を増やしても対応できる。
import Foundation var sum = 0.0 //int型とdouble型は足算できないので,0.0と書きdouble型にする。 let x = Double.pi/3 var item = 1.0 sum += item for i in 1 ..< 6{ item *= -(x*x)/Double((2*i)*(2*i-1)) sum += item } print(sum)//近似値0.499999999639 print(cos(Double.pi/3))//真値0.5第6項までの近似,つまり
$$
cosx=1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+\frac{x^8}{8!}-\frac{x^{10}}{10!}
$$
ではほとんど誤差が無いことがわかる。おまけ
一般化するときは表にすると捉えやすい。
- 投稿日:2020-10-15T20:47:59+09:00
元自衛官実務未経験から受託開発企業から内定もらうまで
今回の記事はタイトル通り実務未経験から企業から内定もらうまで私がどんなことをしたのかを紹介します。
予め言いますがこれが私個人の経験からですのであくまで参考に、、、大まかな筋道
海軍将校になりたくて海自入る->こんな仕事もう嫌ァァァ
↓
辞めた
↓
なんか稼げる仕事ないかな、、、(Youtube漁る)
↓
プログラミングって結構稼げるんだ
とりあえずエンジニア界隈でイケてたKB○Yさんを見習ってFlutterを独学で勉強
↓
挫折
↓
プログラミングスクール通う
なんとなくiOSコースを受講
割とできそうだった
↓
友達の大学生は就活真っ最中で自分も仕事したいと焦る
勉強会やスクールのメンターと話たりしてどんな方法が稼ぐのに最適か調べた
エンジニアとして一番稼げるのは個人で案件を獲得するいわゆるフリーランサー
じゃあiOSの案件ってどんなのあるの
実務経験者募集がほとんど。応募してみてもやっぱダメみたい。
自分がどんなことできるのかアピールできるものが必要->ポートフォリオ
これを宣伝してアピールできないかな
↓
ムリだった、、笑
じゃあ仕事するか。技術磨いてまた挑戦しよう。1ヶ月間だけ就活しようムリなら東京出て頭下げまくってお願いしよう
↓
ここでも実務経験が必要なとこがほとんど。
エージェントやポートフォリオ作っても書類選考も通れない
通れても御堅い企業やSlerとか。もっと自由な働き方したい
↓
Indeedでたまたま上にでできた企業に応募。
とりあえず面接へ。
良さげな雰囲気、後日面接。なんとその後会食がしたいと連絡。
7割受かったと喜びいざ当日。面接というか企業情報を聞いただけその後焼肉奢ってもらった。
無事内定。実際こんな感じ
よくこの職場で働きたいからこの言語で勉強みてみようって目にしますが、実際自分の行きたい会社に入れるのなんて奇跡に近いってか奇跡w
全てタイミングと運でしかなく就活中は「本当に会社行けんのか」って不安でしかたなかった。
先が見えない違業界からの転職ってこんな大変なんだって思い知らされましたね、、、
でも絶対どっか雇ってくれるところはあるし、技術がなくてもなんとかなるって精神はほんとに大事でしたね。毎日4通は違う企業にメールしてたしフレームはあったけどちゃんと毎回違う志望動機でした。(簡単そうに見えて4つ書くのに企業研究含め3、4時間かけてましたね?)
送っても返事は帰って来ないことがほとんどだし心折れかけましたwこんなことしてみては、、、?
私の失敗からこれからエンジニアを目指す方に聞いて欲しいのは、なぜエンジニアを目指しているのか明確にすることですね。
まずprogateとかオンラインスクールに入る前に考えて欲しいです。
エンジニアになって何がしたいのか、どんなエンジニアになっていたいか、本当にエンジニアになりたいのか。など私がエンジニアを目指したのは、この職業が稼げると思ったからです。
実際に稼いでいる方はいますし情報社会で職業がなくなることはほぼないです。
勉強会やエンジニアの方とお話しした中で感じたのは、エンジニアとして稼ぐにはプログラムと〇〇です。
この〇〇はマーケティングや営業、企画や人脈、、、など様々。
どんなものでもどんな人でもチャンスは巡ってます。
でもどんな才能があってめちゃくちゃプログラミングができてもコミュ障じゃ売れないんです。何が言いたいかというと目標がないとやっていけません。
あの人になりたいとかこれがしたいからとかも大事ですが、一番大事なのは「この夢はプログラミングがないとできないわ」って明確な目標。
これめちゃくちゃ難しいです。
でもこの目標があれば面接で強いし挫けかけても立ち直れると思います。
僕はこれを考えるまで苦労しました。最後に
これをみているみなさんがなってよかったと思えるエンジニアになれるよう願っています。
手を動かすのも大事ですが、休憩も大事です。
かのワンピースのミホークも
って言ってます。
休みながらやっていきましょう。。。。
めんどくさくて確認してないので誤字脱字や脈絡のない文章であるかと思いますが、そっとコメントで教えてあげてください。
もしくは、見て見ぬふりでお願いします( ˘ω˘)スヤァ
- 投稿日:2020-10-15T20:17:38+09:00
UIAlertViewControllerをpresentで表示中はUINavigationControllerのスタックを更新できない
複数のUIAlertViewControllerがキューイングされたうえで同時にpresentされるようなイベントがあり、その時に表題の仕様を知らずハマりました。
ハマった一例
// ①イベントの例外処理等で呼ばれるアラート func showCancelOperationDialog() { let alertController = UIAlertController(title: "title", message: "message", preferredStyle: .alert) // OKアクション let defaultAction: UIAlertAction = UIAlertAction(title: "OK", style: .default, handler: { _ in self.moveToFirstViewController() }) // キャンセルアクション let cancelAction: UIAlertAction = UIAlertAction(title: "キャンセル", style: .cancel, handler: nil) alertController.addAction(cancelAction) alertController.addAction(defaultAction) present(alertController, animated: true, completion: nil) } // ②特定のエラーで呼ばれるアラート func showExceptionErrorDialog() { let alertController = UIAlertController(title: "title", message: "message", preferredStyle: .alert) // OKアクション let defaultAction: UIAlertAction = UIAlertAction(title: "OK", style: .default, handler: nil) // キャンセルアクション let cancelAction: UIAlertAction = UIAlertAction(title: "キャンセル", style: .cancel, handler: nil) alertController.addAction(cancelAction) alertController.addAction(defaultAction) present(alertController, animated: true, completion: nil) } // 特定のViewControllerへ戻る処理 func moveToFirstViewController() { guard let firstViewController = self.navigationController?.viewControllers.first as? FirstViewController else { return } self.navigationController?.popToViewController(firstViewController, animated: true) }上記のアラート2種が同時に呼び出され、①
イベントの例外処理等で呼ばれるアラート
-> ②特定のエラーで呼ばれるアラート
の順で実行された場合、①のOKアクションでpopToViewController
が行われません。正確には呼び出しされているのですが表題の通り、presentで表示中はUINavigationControllerのスタックを更新できないため、画面遷移が行われません。回避策
任意のViewControllerに遷移してからアラートを表示させるようにしました。
例外処理としての画面遷移なので遷移 -> アラート表示の順が好ましいですね。
- 投稿日:2020-10-15T19:26:37+09:00
TableViewをスクロールしてデータ更新(上・下それぞれバージョン)
SNSなどで見かける、読み込み済みコンテンツの端までいったら、続きを読み込む方法です。
データ更新部分を準備
データ更新処理を待つためにセマフォを設定します。
let semaphore = DispatchSemaphore(value: 1)リフレッシュ時に以下の関数を呼ぶこととします。
ここで通信リクエストなど行います。func updateData () { DispatchQueue.global().async { //*** ここでデータを更新する処理をする *** DispatchQueue.main.async { self.tableView.reloadData() self.semaphore.signal() // 処理が終わった信号を送る } } }下向きスクロールで更新
下向きに引っ張ってリフレッシュする場合は、UIRefreshControlが使えます。
この記事:[Swift/iOS] フリックで更新するTableViewの方法です。
1、UIRefreshControlを設置します
var refreshControl:UIRefreshControl!override func viewDidLoad() { super.viewDidLoad() refreshControl = UIRefreshControl() refreshControl.attributedTitle = NSAttributedString(string: "再読み込み中") refreshControl.addTarget(self, action: #selector(ViewController.refresh), for: UIControl.Event.valueChanged) tableView.addSubview(refreshControl) }2、リフレッシュ時に呼ばれる関数を設定します
@objc func refresh() { updateData() semaphore.wait() semaphore.signal() // データ更新関数が終了したら、リフレッシュの表示も終了する refreshControl.endRefreshing() }上向きスクロールで更新
TableViewの一番下までスクロールしたら続きを更新する方法。YoutubeなどのUIみたいな。
ScrollViewのデリゲートメソッドを使います。TableViewはScrollViewクラスを継承しているので。func scrollViewDidScroll(_ scrollView: UIScrollView) { let height = scrollView.frame.size.height let contentYoffset = scrollView.contentOffset.y let distanceFromBottom = scrollView.contentSize.height - contentYoffset if distanceFromBottom < height { if self.reloading { // デリゲートは何回も呼ばれてしまうので、リロード中はfalseにしておく updateData() semaphore.wait() semaphore.signal() self.reloading = false } } }?
お仕事のご相談こちらまで
rockyshikoku@gmail.comCore MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。
- 投稿日:2020-10-15T19:24:19+09:00
Youtube Data APIのリクエスト結果表示数(resultsPerPage)を変える
デフォルトでは「5」だけ表示されます。
"pageInfo": { "totalResults": 40, "resultsPerPage": 5 }次の5個を取得するには、結果に含まれる「NextPageToken」をリクエストURLにつけます。
https://www.googleapis.com/youtube/v3/playlists?part=snippet&channelId={CHANNEL_ID}&key={API_KEY}&pageToken={PAGE_TOKEN}最初から取得する数を増やすには、「max_Results」をリクエストURLにつけます。
https://www.googleapis.com/youtube/v3/playlists?part=snippet&channelId={CHANNEL_ID}&key={API_KEY}&&maxResults=20"pageInfo": { "totalResults": 40, "resultsPerPage": 20 }?
お仕事のご相談こちらまで
rockyshikoku@gmail.comCore MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。
- 投稿日:2020-10-15T18:09:27+09:00
ARKit + Metalで手をゆらゆらさせてみる
ARKitとMetalを使って手をゆらゆらさせる方法を紹介します。
考え方
ARKitのPeople Occlusionを使用します。
People Occlusionを使用すると人型のマスクテクスチャが得られるので、そのマスクとカメラの画像を同時に歪ませて、歪んだ合成用画像を取得します。歪んだまま切り取る感じです。
こんな画像が取得できます(わかりやすくするために動画よりも強めに歪ませています)
この歪ませた手の映像と、元の映像を重ねることで上のような動画を作ることができます。
手順
1.Appleの公式サンプルを入手する
Appleの公式サンプルにPeople Occlusionを使用して人型のマスクテクスチャを得る処理が書かれているため、これをベースに書いていきます。
Effecting People Occlusion in Custom Renderers
2. シェーダーに経過時間を渡す
ゆらゆらさせるには、経過時間を変形式に与える必要があります。
シェーダーに渡すstructを宣言します。
Renderer.swiftstruct Uniforms { var time: Float = 0 }次に、経過時間を管理するための変数と、開始時間を宣言します。
Renderer.swiftclass Renderer { var uniforms = Uniforms() private var startDate: Date = Date() var uniformsBuffer: MTLBuffer! // シェーダに渡すためのバッファそしてシェーダに情報を渡しているcompositeImagesWithEncoderメソッドの中で一緒に経過時間を渡してあげます。
Renderer.swiftuniforms.time = time uniformsBuffer = device.makeBuffer(bytes: &uniforms, length: MemoryLayout<Uniforms>.stride, options: []) uniformsBuffer.label = "UniformsBuffer"シェーダー側でもSwift側と同じstructを用意しておき、関数の引数として受け取ります。
引数名はmyUniformsとしています。Shaders.metalstruct Uniforms { float time; }; fragment half4 compositeImageFragmentShader(CompositeColorInOut in [[ stage_in ]], texture2d<float, access::sample> capturedImageTextureY [[ texture(0) ]], texture2d<float, access::sample> capturedImageTextureCbCr [[ texture(1) ]], texture2d<float, access::sample> sceneColorTexture [[ texture(2) ]], depth2d<float, access::sample> sceneDepthTexture [[ texture(3) ]], texture2d<float, access::sample> alphaTexture [[ texture(4) ]], texture2d<float, access::sample> dilatedDepthTexture [[ texture(5) ]], constant SharedUniforms &uniforms [[ buffer(kBufferIndexSharedUniforms) ]], constant Uniforms &myUniforms [[buffer(kBufferIndexMyUniforms)]]) {3. シェーダーを書き換える
公式サンプルのうち、Shaders.metalのcompositeImageFragmentShader関数を次のように書き換えます。
Shaders.metal@@ -219,8 +397,9 @@ fragment half4 compositeImageFragmentShader(CompositeColorInOut in [[ stage_in ] half4 sceneColor = half4(sceneColorTexture.sample(s, sceneTexCoord)); float sceneDepth = sceneDepthTexture.sample(s, sceneTexCoord); + float2 modifier = float2(sin(cameraTexCoord.y + myUniforms.time*5)*0.2, 0); // 変形の式 half4 cameraColor = half4(rgb); - half alpha = half(alphaTexture.sample(s, cameraTexCoord).r); + half alpha = half(alphaTexture.sample(s, cameraTexCoord + modifier).r); // 人型マスクを変形させる half showOccluder = 1.0; @@ -233,8 +412,11 @@ fragment half4 compositeImageFragmentShader(CompositeColorInOut in [[ stage_in ] showOccluder = (half)step(dilatedDepth, sceneDepth); // forwardZ case } + float2 displacedUV = sceneTexCoord + modifier; // 画像を変形させる - half4 occluderResult = mix(sceneColor, cameraColor, alpha); + half4 displacedCol = half4(sceneColorTexture.sample(s, displacedUV)); // 変形した人型画像の取得 + half4 occluderResult = mix(sceneColor, displacedCol, alpha); // 変形した画像と元の画像を合成 half4 mattingResult = mix(sceneColor, occluderResult, showOccluder); return mattingResult; }重要なのはここです。
Shaders.metalfloat2 modifier = float2(sin(cameraTexCoord.y + myUniforms.time*5)*0.2, 0); // 変形の式sin関数に入力画像のy座標と、経過時間を足したものを与え、これをmodifyerに代入しています。
modifierはカメラや人型マスクに加算するための変数で、今回はxだけに式が入っているので、x軸方向だけがゆらめくことになります。なお、実際の動画は縦方向にゆらいでいるので、上の式と矛盾しますがこれは、iPhoneをランドスケープの状態で録画したものを、画像編集ソフトで縦に変換したためです。
図形の変形については、こちらの記事に書きましたので、こちらもご覧ください。
ARKitやSceneKitの図形をMetalシェーダーで変形させる方法
仕上がり
Youtubeにも動画をアップしています。
仕上がりの動画(Youtube)最後に
NoteではiOS開発について定期的に発信していますので、フォローしていただけますと幸いです。
https://note.com/tokyoyoshidaTwitterでは簡単なtipsを発信しています。
https://twitter.com/jugemjugemjugem
- 投稿日:2020-10-15T01:34:55+09:00
iOS14で動画再生中、バックグラウンド移行時に一時停止されてしまう問題への対応
対応
playerView.player = nil
playerView.player = player
の実行タイミングを変更する
@objc func applicationWillResignActive(_ notification: NSNotification?) { playerView.player = nil } @objc func applicationDidBecomeActive(_ notification: NSNotification?) { playerView.player = player }経緯
- ユーザー「iOS14にアップデートしたらバックグラウンド再生がおかしい。なんとかしろ」
- ワタクシ「」
対応前
applicationDidEnterBackground
でplayerView.player = nil
していた ※Appleさんの公開しているドキュメントの記載内容に従ったもの調査
- 何もしてないのに動かなくなった ⇒ OSの仕様変わったな?
- バックグラウンドに行ったら一時停止 ⇒ layerにplayer設定したままの動作と同じだな?
検証
- 動画再生中、バックグラウンド移行前に、手動で
playerView.player = nil
する- バックグラウンドへ移行する
⇒「再生が継続された!」
導き出される結論は…
「layer に player があるかどうかチェックしているタイミング変わったんじゃね?」再検証
applicationDidEnterBackground
より前に実行されるapplicationWillResignActive
でplayerView.player = nil
するよう変更applicationWillResignActive
に対となるのがapplicationDidBecomeActive
となるため、そこでplayerView.player = player
するよう変更⇒「再生が継続された!」
※iOS11-14、iPadOS13,14で動作することも確認しました
まとめ
- Appleさんのドキュメントのままに書いても動作しないため、OS不具合の可能性が高いです
- iOS 14.2 beta2 で、この不具合が修正されているとの噂です
その他
- iOS14がリリースされてしばらく経ちましたが、この対応方法を見かけなかったため記事を投稿します
参考文献
- 投稿日:2020-10-15T00:45:36+09:00
iOS14のSwiftUIではリストのスクロール処理をコードで制御できるようになった
はじめに
iOS13のSwiftUIではできなかったコードによるリストのスクロール処理が、iOS14ではできるようになりました。
本記事でその実装方法をまとめています。iOS13でのスクロール処理
iOSアプリを開発しているとよくある「○番目のセルに自動でスクロールする」という処理ですが、
これをiOS13のSwiftUIでは実現する方法がありませんでした。struct ContentView: View { var body: some View { List(0..<100) { Text("\($0)") } } }UIKitでは以下のような形で、
scrollToRow
,scrollToItem
などのメソッドを呼び出す形で該当の要件を簡単に実装できるので、
この機能のためだけにUIViewRepresentable
,UIViewControllerRepresentable
などを利用することもしばしばありました。// UITableView tableView.scrollToRow(at: IndexPath(row: 10, section: 0), at: .top, animated: true) // UICollectionView collectionView.scrollToItem(at: .init(item: 10, section: 0), at: .top, animated: true)iOS14でのスクロール処理
iOS14では
ScrollViewReader
というスクロール状態を制御できる新しいViewが追加されており、
これを利用すると任意の地点に自動でスクロールさせる処理の実装が可能になります。以下にサンプルコードを示します。
準備
まずは、準備としてスクロール地点を指定するためのTextFieldを設置します。
struct ContentView: View { @State private var text: String = "" var body: some View { VStack { HStack { TextField("input row number", text: $text) Button("Scroll") { guard let row = Int(text) else { return } print(row) } }.padding() List(0..<100) { Text("\($0)") } } } }これにより、ボタンをタップするとユーザーがTextFieldに入力した値を取得できるようになります。
スクロール制御
それでは実際にスクロールさせる処理の実装部分です。
まずはスクロール制御をしたい箇所を
ScrollViewReader
で囲います。
これによりスクロール制御が可能なScrollViewProxy
インスタンスの取得ができるようになります。struct ContentView: View { @State private var text: String = "" var body: some View { VStack { + ScrollViewReader { (proxy: ScrollViewProxy) in HStack { TextField("input row number", text: $text) Button("Scroll") { guard let row = Int(text) else { return } } }.padding() List(0..<100) { Text("\($0)") } + } } } }さらに、スクロール位置を特定するためのIDを対象のViewに対して付与しておき、
制御を開始したい部分でScrollViewProxy
のscrollTo
メソッドにそのIDを指定するだけでスクロール処理を実現することができます。struct ContentView: View { @State private var text: String = "" var body: some View { VStack { ScrollViewReader { (proxy: ScrollViewProxy) in HStack { TextField("input row number", text: $text) Button("Scroll") { guard let row = Int(text) else { return } + withAnimation { + proxy.scrollTo(row, anchor: .top) + } } }.padding() List(0..<100) { Text("\($0)") + .id($0) } } } } }これでやりたいことが実現できるようになりました。
ちなみに
withAnimation
を付与しなければ、スクロールのアニメーションは行われなくなります。
また、第二引数のanchor
でスクロール後の位置を細かく指定できます。おまけ
Gridに対しても問題なく動作しました。
struct ContentView: View { @State private var text: String = "" var body: some View { VStack { ScrollViewReader { (proxy: ScrollViewProxy) in HStack { TextField("input row number", text: $text) Button("Scroll") { guard let row = Int(text) else { return } withAnimation { proxy.scrollTo(row, anchor: .top) } } }.padding() ScrollView { LazyVGrid( columns: [ GridItem(.flexible(minimum: 0, maximum: .infinity)), GridItem(.flexible(minimum: 0, maximum: .infinity)), ], alignment: .center, spacing: nil ) { ForEach(0..<100) { Text("\($0)") .frame(height: 100) } } } } } } }
- 投稿日:2020-10-15T00:44:15+09:00
Cookiecutterを使って爆速でiOSプロジェクトを作成する
はじめに
あなたは開発スタート時に毎回新しいXcodeプロジェクトを作っていませんか?
過去のプロジェクトから使ってもいいヤツらを 「Add Files to」していませんか?
xcconfigやcarthageの設定を毎回行っていませんか?そうです、まさに私のことです。
というわけで、開発初期のスピードを加速させるべく
Cookiecutter というPythonのツールを利用してコマンド一発
で
iOSプロジェクトを作成している例があったので真似してみることにしました。クイックスタート
サンプルとしてCleanArchitectureでの開発用テンプレートを作成してみました。
https://github.com/SatoshiN303/iOS-Blueprints-CleanArchitecture$ brew install cookiecutter $ cookiecutter https://github.com/SatoshiN303/iOS-Blueprints-CleanArchitecture.git上記のコマンドを叩くと 「アプリ名」 「会社名」 「バンドルID」が聞かれます。
それぞれを入力するとプロジェクト作成完了です。
生成されるサンプルプロジェクトについて
- bootstrap.sh
- .xcconfig (debug/adhoc/release)
- CocoaPods Settings
- Carthage Setting
- no Main.storyboard
- DependencyInjection SampleCode
- Github's Repositry search process SampleCode
テンプレートの基本的な内容として上記を設定してみました。
普段通りに実装したものをCookiecutterテンプレートとして転用できるのは便利です。ちなみに開発時には削除することになりますが
GitHubAPIを叩いて画面に表示するサンプルコードを追加しています。
理由としてCleanArchitectureで誰が何の責務を持っているか把握する為になります。
Cookiecutterについて
主に機械学習向けのPythonパッケージやDjango等の
プロジェクトテンプレートを作成することができるツールです。cookiecutter-template を確認すると様々なテンプレートが公開されています。
まずは Forkして カスタマイズするのも有かなと思います。Android向けやiOS向けもそれなりにありました。
ちなみにローカルでも利用可能でした。# Create project in the current working directory, from the local # cookiecutter-pypackage/ template $ cookiecutter cookiecutter-pypackage/補足: Xcodeのプロジェクトテンプレートを使わなかった理由
Xcodeのオレオレプロジェクトテンプレート作成も試みたのですが
以下の理由で色々と面倒だったので cookiecutter を使う感じになりました。
- TemplateInfo.plist をガッツリ弄るのが億劫
- xcconfig とか BuildSettingsも設定したい
Xcodeの自作プロジェクトテンプレートに詳しい方などいらっしゃいましたら
コメント頂けると幸いでございます?♂️今後やりたいこと
- 再利用できるものはEmbedded Framework化した上でテンプレートに含める
- 他のアーキテクチャも作りたい
- テンプレートプロジェクト自体をCIで回してテンプレートの形骸化を防ぎたい
- シェルスクリプト使ってAWS Amplifyも合わせて設定する
まとめ
Cookiecutter向けに自分好みのテンプレートを作って開発初期スピードを加速させよう
参考
- 投稿日:2020-10-15T00:12:48+09:00
XCode12でビルド先をシミュレーターにするとビルドできない!
ビルド先をシミュレーターにするとビルドできない!
XCode12からビルドシステムが変わったみたいで、
building for iOS Simulator, but linking in object file built for iOS, for architecture arm64
エラーが発生し、ビルドできないプロジェクトがあるみたいです。解決方法
arm64をArchitecturesからはずせばいいらしい。
Build Settings > Architectures > Excluded Architectures > Any iOS Simulator SDK = arm64
CocoaPodsの設定
CocoaPodsのライブラリでエラーが出ている場合は、
Podfile
に↓を追記する。Podfilepost_install do |installer| installer.pods_project.build_configurations.each do |config| if config.name == "Develop" config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64' end end end