20211008のSwiftに関する記事は9件です。

UITextField leftViewについて

今回の内容 コードと簡単解説 .leftViewを設定することで、TextField内の左側にUIViewを作成することが出来ます。 .leftViewが存在すると入力される文字の位置が.leftViewのframe分だけ横に移動します。 let textfield01 = UITextField() textfield01.frame = CGRect(x: view.frame.maxX / 10, y: view.frame.maxY / 11, width: view.frame.width - (view.frame.maxX / 5), height: 50) textfield01.placeholder = "UITextField01" textfield01.layer.cornerRadius = 10.0 textfield01.layer.borderWidth = 1.0 textfield01.leftView = UIView(frame: CGRect(x: 2, y: 2, width: textfield01.frame.height, height: textfield01.frame.height)) textfield01.leftView?.backgroundColor = .systemGreen textfield01.leftViewMode = .always textfield01.layer.borderColor = UIColor.black.cgColor textfield01.backgroundColor = .white view.addSubview(textfield01) 終わり ご指摘、ご質問などありましたら、コメントまでお願い致します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

# [Swift] 複数の ビルドTARGET へ Swift Package Manager でライブラリを入れる

[Swift] Swift Package Managerでライブラリを入れる 複数のビルドTARGETにライブラリを入れる際のメモ 1、swift packagesからライブラリを入れる。 iOSアプリ開発にSwift Package Managerを使おう 今回はQGridをプロジェクトへ導入する。 (1) File → Swift packages → add package dependency (2) プロジェクトへ導入したいライブラリのgit url (https://github.com/Q-Mobile/QGrid) を入れる この時点では、ビルドtargetを一つしか選択できない。 2、他のビルドTARGETにも入れる addで導入完了
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Swift] 複数の ビルドTARGET へ Swift Package Manager でライブラリを入れる

[Swift] Swift Package Managerでライブラリを入れる 複数のビルドTARGETにライブラリを入れる際のメモ 1、swift packagesからライブラリを入れる。 iOSアプリ開発にSwift Package Managerを使おう 今回はQGridをプロジェクトへ導入する。 (1) File → Swift packages → add package dependency (2) プロジェクトへ導入したいライブラリのgit url (https://github.com/Q-Mobile/QGrid) を入れる この時点では、ビルドtargetを一つしか選択できない。 2、他のビルドTARGETにも入れる addで導入完了
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[SwiftUI] 変数の値をNavigationLinkのdestinationに指定して画面遷移できるようにしたい。

概要 使いまわせるviewは、できるだけ細かく作って、車輪の再開発だけは避けたい!!! と思い、List用のcellのviewを作成。 しかし、cellにあるNavigationLinkのdestinationプロパティの値で怒られ、ハマる。。。 Cannot find type 'Destination' in scopeで怒られ、引数に遷移したいviewを渡せない。。。 struct NavigationLinkView: View { var body: some View { VStack(spacing: 30) { NavigationLinkCell(title: "home", destination: HomeView()) NavigationLinkCell(title: "favorite", destination: FavoriteView()) NavigationLinkCell(title: "test", destination: TestView()) } } } struct NavigationLinkCell: View{ let title: String let destination: Destination var body: some View { NavigationLink(destination: destination) { Text(title) } } } struct HomeView: View { var body: some View { Text("HomeView") } } struct FavoriteView: View { var body: some View { Text("FavoriteView") } } struct TestView: View { var body: some View { Text("TestView") } } 解決策 "Destination : View"  型をつけてやります。 struct NavigationLinkCell<Destination : View>: View{ let title: String let destination: Destination var body: some View { NavigationLink(destination: destination) { Text(title) } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[SwiftUI] 変数の値をNavigationLinkのdestinationに指定して遷移できるようにしたい。

概要 使いまわせるviewは、できるだけ細かく作って、車輪の再開発だけは避けたい!!! と思い、List用のcellのviewを作成。 しかし、cellにあるNavigationLinkのdestinationプロパティの値で怒られ、ハマる。。。 Cannot find type 'Destination' in scopeで怒られ、引数に遷移したいviewを渡せない。。。 struct NavigationLinkView: View { var body: some View { VStack(spacing: 30) { NavigationLinkCell(title: "home", destination: HomeView()) NavigationLinkCell(title: "favorite", destination: FavoriteView()) NavigationLinkCell(title: "test", destination: TestView()) } } } struct NavigationLinkCell: View{ let title: String let destination: Destination var body: some View { NavigationLink(destination: destination) { Text(title) } } } struct HomeView: View { var body: some View { Text("HomeView") } } struct FavoriteView: View { var body: some View { Text("FavoriteView") } } struct TestView: View { var body: some View { Text("TestView") } } 解決策 "Destination : View"  型をつけてやります。 struct NavigationLinkCell<Destination : View>: View{ let title: String let destination: Destination var body: some View { NavigationLink(destination: destination) { Text(title) } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】URLはStringからデコードできる

偶然気づいたのですが、JSONをデコードする際にURLは直接Stringからデコードできるみたいです。 例えばこういうJSONがあったとします。 let jsonString = """ { "url": "https://example.com/", } """ この時に作成するモデルは struct Example: Decodable { let url: URL } と書く事ができます。let url: Stringとしなくても良いという事です。 試しにデコードしてみます。 let example = try JSONDecoder().decode(Example.self, from: jsonString.data(using: .utf8)!) // Example(url: https://example.com/) print(example) // URL print(type(of: example.url)) どうやらちゃんとURL型にデコードされているみたいです。 今度は不当なStringを与えてみます。 let jsonString = """ { "url": " ", } """ struct Example: Decodable { let url: URL } let example = try JSONDecoder().decode(Example.self, from: jsonString.data(using: .utf8)!) Playground execution terminated: An error was thrown and was not caught: ▿ DecodingError ▿ dataCorrupted : Context ▿ codingPath : 1 element - 0 : CodingKeys(stringValue: "url", intValue: nil) - debugDescription : "Invalid URL string." - underlyingError : nil デコードエラーとなりました。ちゃんと確認はしてませんが、このバリデーションはURL.init(string:)と同じかもしれません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SwiftのClosureにおける `$0` とは結局何者なのか

先日、業務でSwiftのClosureについて説明する機会があったのですが、「SwiftのClosureにおける $0 とは何なのか」をうまく説明できなかったので悔しくて調べました。 そもそもClosureってなんだっけ。 Swift.orgによると、下記の定義となっています。 Closures are self-contained blocks of functionality that can be passed around and used in your code. 訳: クロージャーは、コード内で受け渡して使用できる機能の自己完結型のブロックです。 この機能(原文ではfunctionality) という部分が大事で、Closureを利用するとなにか任意の振る舞いを別のどこかに受け渡し、自身のコードの箇所ではない全然別の場所で振る舞いを起こすことができるというのが面白い点だと思っています。 (ここでの 振る舞い はなにか変数を操作したり、成功時のハンドラだったりというようなプログラムとしての動き全般を指しています) Closureってどう書くんだっけ & $0ってなんだっけ。 SwiftのClosureは下記のように記述することができます let result: ((Int) -> Bool) = { price -> Bool in if price < 1500 { return true } else { return false } } これだけだとシンプルなので、下記のようにもっと短くすることができます let result((Int) -> Bool) = { price -> Bool in return price < 1500 } この書き方をする場合、return price <= 1500の改行すらも取り除くことができるので、下記のようにきれいにすることができます let result((Int) -> Bool) = { price -> Bool in return price < 1500 } ClosureのShorthand Argument Names 上記を何度も定義から書くのはしんどいため、ここでSwiftが気を利かせてくれて、クロージャーが1行のときは、クロージャー内部で利用することができる $0 系の仮引数を設定してくれます let result: ((Int) -> Bool) = { return $0 < 1500 } Swift.org上だと下記のように説明しています Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names \$0, \$1, \$2, and so on. 訳: Swiftは、インラインクロージャに短縮引数名を自動的に提供します。これを使用して、クロージャの引数の値を$ 0、$ 1、$ 2などの名前で参照できます。 このため、SwiftのClosureでよく使っている $0 は実は、Swiftが気を利かせて作ってくれている 仮引数名なのだよ、という話でした。 補足: $0は衝突します。 (良いか悪いかはおいておいて)closureの中にclosureを書こうとする場合、 Shorthand Argument Names を利用すると名前が衝突してコンパイルできなくなります let sources = [[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]] sources.forEach({ print($0.forEach({ print($0) }) }) // ↑ $0の名前が衝突してコンパイルできなくなる なので、この場合は素直に引数名を定義してあげましょう let sources = [[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]] sources.forEach({ values -> Void in print(values.forEach({ value -> Void in print(value) })) }) 上記の例ではどちらにも引数を定義していますが、 $0 が衝突さえしなければ大丈夫なので、どちらか片方だけでも大丈夫だと思います(多分) これで明日からコンパイルエラーに困っても多分大丈夫です!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RxSwift で独自のリトライ処理を実現

はじめに エラーが流れてきたときに指定回数、指定条件でリトライする処理は標準オペレータとして提供されており、 retry もしくは retryWhen を利用します。 今回はこのようなエラーが流れてきたときではなく、「nil だったとき」のような独自のリトライトリガーを実現する方法をご紹介します。 方針 flatMap で特定条件時に独自のエラーに変換する flatMap の中で timer で遅延させて自身を再帰的に呼び出す ザッとこの2パターンを思いつきました。 1に関しては、リトライ処理のためにエラーを新しく定義するのはどうなのかという点、2はリトライ回数を制御するためにグローバル変数を定義する必要がある点が個人的に感じた悩みポイントです。 実装環境に合わせた判断と工夫を追加で施していただければと思います。 1. エラーに変換してリトライ enum CustomeError: Error { case nilData } private func fetch() -> Observable<Data> { API.fetch() .flatMap { res -> Observable<Data> in guard let data = res else { return .error(CustomeError.nilData) } return .just(data) } .retry(3) // 標準オペレータの利用 } 2. 再帰処理を利用してリトライ private func fetch() -> Observable<Data> { API.fetch() .flatMap { res -> Observable<Data> in guard let data = res else { // 5 秒間隔でリトライ return Observable<Int>.timer(.seconds(5), scheduler: MainScheduler.instance) .flatMap { [unowned self] _ in // リトライ回数を制御する場合はここで判定 self.fetch() // 再帰 } } return .just(data) } } おわりに RxSwift の利用方法メモとして書いてみました。 ご指摘等ございましたら、コメント頂けますと幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Swift5 MainMenuのitemがenable状態から変わらない場合の対処法

Xcode: v13.0 Swift: 5.5 事象 XcodeでOSX用のMainMenuの各item(NSMenuItem)enable/disable制御を実装しようとした際enable状態から変わらない状態が発生したので、その際の対処法をメモします。 storyboard上ではdisable状態のはずなのに・・ RUNするとenable状態になってしまう・・ 立ち上げ段階ではdisable状態であって欲しい!! 解決策 AutoEnables Itemsのチェックを外す。 上記にチェックが入っていると自動でmenuitemがenable状態になってしまいます。そのような状態を望まない場合はチェックを外しましょう!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む