- 投稿日:2021-07-15T23:13:32+09:00
UIActivityIndicatorView
UIActivityIndicatorView コード Indicator Indicator import Foundation import UIKit class Indicator:UIViewController{ let activityIndicator = UIActivityIndicatorView() //インスタンス化 func createIndicator(targetView:UIView){ activityIndicator.center = targetView.center //真ん中に表示 activityIndicator.style = .large //表示するスタイルを設定 activityIndicator.color = .black //indicatorの色を設定 targetView.addSubview(activityIndicator) } } ViewController ViewController import UIKit class ViewController: UIViewController { let indicator = Indicator() var indicatorCount = 0 //indicatorのアニメーションのStartかStopかを判定させるための変数 override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) indicator.createIndicator(targetView: self.view) //indicator作成 } @IBAction func indicatorStartStop(_ sender: Any) { if indicatorCount == 0{ indicator.activityIndicator.startAnimating() indicatorCount = indicatorCount + 1 }else if indicatorCount == 1{ indicator.activityIndicator.stopAnimating() indicatorCount = indicatorCount - 1 } } } 終わり iOSアプリ開発を始めて2週間目くらいの時に、indicatorをクルクルさせただけでも感動してたなぁ
- 投稿日:2021-07-15T19:35:48+09:00
YOLOv4 を iOS で動かそうとして残念だった話
はじめに iOS でとにかく速く正確に動くモデルを模索する今日この頃 こちらの素晴らしい記事を参考に YOLOv4 を動かしてみたのですが、、、 実行環境 macOS Big Sur 11.4(20F71) XCode 12.5.1 (12E507) iPhone SE2 coremltools 3.3 , 4.1 クラッシュ 上記記事を参考にモデルを変換し、 yolov4.mlmodel を手に入れました 嬉々として動かしてみたところ、、、 実行時に見事にクラッシュしました 念の為、 coremltools の 3.3 と 4.1 のそれぞれで変換しましたが、どちらもダメです なぜ? 調査結果 調べてみると、 coremltools の Issues に行き当たりました どうも現在の環境でカスタムレイヤーがあるとダメのようです 修正 以下のように修正することで動作しました ※付随して修正が必要なところもありますが省略します let model = yolov4() public init() { } let model: yolov4? public init() { let config = MLModelConfiguration() config.computeUnits = MLComputeUnits.cpuAndGPU let url = Bundle.main.url(forResource: "yolov4", withExtension: "mlmodelc")! let mlmodel = try! MLModel(contentsOf: url, configuration: config) self.model = yolov4(model: mlmodel) } コンフィグに指定している config.computeUnits = MLComputeUnits.cpuAndGPU は、モデルが CPU もしくは GPU しか使わないようにするものです より高速な Neural Engine は使わないようになります 動きましたが、iPhone SE2 で 6 FPS 程度しか速度が出ず 結局、別のモデルを使った方が良さそうです
- 投稿日:2021-07-15T15:28:17+09:00
[Swift]for文とforEachのどちらを使うか
※この記事はSwift by Sundellの内容を日本語に翻訳したものです。 ArrayやSetなどのコレクションを反復処理する場合、最初は、従来のforループを使用するか、クロージャーベースのforEachメソッドを使用するかは、好みとスタイルの問題のように思われるかもしれません。これらの2つのメカニズムが非常に類似していることは確かですが、いくつかの点で異なります。 これらの違いの1つは、forループの反復がコードの制御フロー内で直接実行されることです。これにより、これらの反復をより正確に制御できます。たとえば、continueキーワードを使用して任意の時点で次の要素にスキップするか、breakを使用して反復を完全に中断するかを選択できます。 func recentArticles(among articles: [Article]) -> [Article] { var results = [Article]() for article in articles { guard !article.isDraft else { // すぐに次の要素にスキップします。 continue } results.append(article) guard results.count < 5 else { // 反復を中断します。この場合、ここに直接戻ることもできます。 break } } return results } forループの反復が(上記のように)フィルタリングに使用されるguard(またはif)ステートメントで始まる場合、代わりにwhereベースのパターンマッチングを使用してそのロジックを実装することもできます—次のように: for article in articles where !article.isDraft { results.append(article) guard results.count < 5 else { break } } 上記の種類の制御フロー関連の機能は、forループを非常に強力にする大きな部分ですが、そのレベルの制御が必要ない場合は、forEachの呼び出しを使用すると、コードが少し単純に見える可能性があります。たとえば、ここでは、配列の要素ごとに新しいビューを追加しています。これは、forEachを使用して非常にエレガントに実行できます。 func addArticleViews(for articles: [Article]) { articles.forEach { article in let articleView = ArticleView() // クロージャーの article を使用して新しいビューを設定します。 ... view.addSubview(articleView) } } ただし、Swiftのファーストクラス関数機能を使用する方がおそらくさらにエレガントです。上記のメソッドをリファクタリングして単一のArticleのみを受け入れ、そのメソッドをforEachの呼び出しに直接挿入します。 class ArticleGroupViewController: UIViewController { private let articles: [Article] ... override func viewDidLoad() { super.viewDidLoad() ... articles.forEach(addArticleView) } private func addArticleView(for article: Article) { let articleView = ArticleView() ... view.addSubview(articleView) } } 要約すると、forループを使用すると、反復をより高度に制御できます。一方、forEachを使用すると、一度開始すると反復を停止することはできませんが、クロージャとファーストクラス関数の機能を利用できます(エラーをスローすることは別として)。 元の記事 Picking between a for loop and forEach Swift by Sundell
- 投稿日:2021-07-15T15:01:20+09:00
[Swift]同じ名前の変数に式を割り当てる
※この記事はSwift by Sundellの内容を日本語に翻訳したものです。 Swift 5.4の新機能: selfを使って手動で明確にすることなく、同じ名前の式に割り当てられるローカル変数を作成できるようになりました。 たとえば、次のItemListViewControllerには、単にitem(at :)を呼び出すように選択した特定のIndexPathのアイテムを取得できるメソッドがあります。 class ItemListViewController: UIViewController { ... private func item(at indexPath: IndexPath) -> Item { ... } } Swift 5.3以前を使用しているときに、上記のメソッドを呼び出して、その結果をitemとも呼ばれるローカルのletまたはvarに割り当てる場合、コンパイラーが使用できるようにするには、メソッド呼び出しの前にselfを付ける必要があります。 2つを分けるには—次のように: class ItemListViewController: UIViewController { ... private func showDetailViewForItem(at indexPath: IndexPath) { let item = self.item(at: indexPath) ... } } ただし、Swift 5.4以降、これは不要になり、コンパイラは、selfを使用して参照するかどうかに関係なく、右側のアイテムシンボルがメソッドの呼び出しを参照していることを自動的に認識します。 class ItemListViewController: UIViewController { ... private func showDetailViewForItem(at indexPath: IndexPath) { let item = item(at: indexPath) ... } } おそらく、この新しい構文機能を使用する私のお気に入りの方法は、非同期コードの単体テストを作成するときです。これには通常、組み込みのexpectationAPIを使用してXCTestExpectationインスタンスを作成することが含まれます。このような期待の最も自然な名前は単にexpectationであることが多いため、次のことができるようになったのは本当に素晴らしいことです。 class ItemLoaderTests: XCTestCase { ... func testLoadingItem() { let expectation = expectation(description: "Loading item") ... } } 上記の機能が役立つもう1つのタイプの状況は、プロパティのローカルで変更可能なコピーを作成する場合です。これは、コピーするプロパティを参照するときにselfを使用せずに実行できるようになりました。たとえば、次のようになります。 struct Item { var title: String var prefix: String? var suffix: String? func fullTitle() -> String { var title = title // 従来は var title = self.title if let prefix = prefix { title = prefix + title } if let suffix = suffix { title += suffix } return title } } 確かに、これはSwiftコードの記述方法を完全に変える革新的な新しい構文機能ではないかもしれませんが、すべての機能や変更が必要なわけではありません。個人的には、このような「生活の質」の向上は非常に歓迎されており、特定の種類のコードをかなり軽量に感じさせることができると思います。 元の記事 Assigning an expression to a variable with the same name Swift by Sundell
- 投稿日:2021-07-15T09:46:01+09:00
SwiftのUserdefaultsに関して
UserDefaults 一言でいえばJavascriptのLocalStorageと同じもの。 起動した際にアプリ内にデータを保存してくれるキーバリュー型のDB。 なんのためのUserDefaults データベースを保存しておきたいけど、DBにわざわざ渡す程でもないデータを送るため。 アプリを削除すると同時に消えるため重要なデータは保存できないが設定などの簡単なデータは入れられる。 書き方 UserDefaults.swift //データを追加or更新 UserDefaults.standard.set({値}, forKey: {キー}) //データを取り出す UserDefaults.standard.データ型(forKey:{キー名}) //データ型はobject int string double float dictionally data 等 //データを削除する UserDefaults.standard.removeObject(forKey:{キー名}) //専用データ型がない限りは下の文字をつけて型キャストしてあげる as? Date 構造体も保存できる kozotai.swift //構造体の宣言 struct Person: Codable { let name: String let age: Int } /// 保存 let saveData = Person(name: "bokuboku", age: 23)//インスタンス化して変数へ let encoder = JSONEncoder()//JSONエンコーダーをインスタンス化 if let encodedData = try? encoder.encode(saveData) { UserDefaults.standard.set(encodedData, forKey: "person") } /// 読み込み if let savedValue = UserDefaults.standard.data(forKey: "person") { let decoder = JSONDecoder()//Jsonデコードをインスタンス化 if let value = try? decoder.decode(Person.self, from: savedValue) { print(value) // Person(name: "bokuboku", age: 23) } } else { /// 値がない場合の処理 print("無いよ") }