20220114のSwiftに関する記事は5件です。

「Sign in with Apple」ボタンのサイズを変更する方法

結論 コードでAutoLayoutすればイケる。 ViewController.swift // ボタンの生成 let authorizationButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white) // コードでAutoLayoutするためのおまじない(意味を知りたい方は調べてください) authorizationButton.translatesAutoresizingMaskIntoConstraints = false // Storyboardで作成済みのUIStackViewに追加 self.signInBtnStackView.insertArrangedSubview(authorizationButton, at: 0) // サイズ比率のAutoLayoutを記述(この場合は5:1の割合になる) authorizationButton.widthAnchor.constraint(equalTo: authorizationButton.heightAnchor, multiplier: 5/1).isActive = true Sign in with Appleボタンとは アプリ内でログインが必要な場合に、自前のサーバーでアカウントを管理せずにApple IDを利用してログインしてもらうことができる機能が「Sign in with Apple」。 そしてその機能を利用する際に、自身でログインボタンを作らなくてもAppleがログインボタンのクラス(ASAuthorizationAppleIDButton)を用意してくれているので、開発者はそれをViewに追加するだけで済むというボタンのこと。 iPhoneユーザーなら一度は見たことであろうあのボタンである。 Apple公式より引用 自分で用意しなくていいのは楽だけど、、、 例えばFirebase Authなどで「Sign in with Google」も一緒に設置する場合、こちらも同じくGoogleが用意しているGIDSignInButtonを利用することができる。がしかし、 このように、GoogleとAppleがデフォルトにしているボタンの大きさが異なるのでどちらかを揃えなければならない。 気にしなければよいという意見があるかもしれないが、Appleのドキュメントに Make a Sign in with Apple button no smaller than other sign-in buttons (他のサインインボタンより小さくしないで!) と明記されているので恐らくこのままではリリース審査で指摘されてしまう。 bounds変えれば良いのでは? ViewController.swift // ボタンの生成 let authorizationButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white) // Storyboardで作成済みのUIStackViewに追加 self.signInBtnStackView.insertArrangedSubview(authorizationButton, at: 0) // boundsのサイズを変更 authorizationButton.bounds.size = CGSize(width: <CGFloat>, height: <CGFloat>) こんな感じで、boundsのサイズを変えてみるも、UIStackViewでAutoLayoutが使用されるためコードでのサイズ変更は全く効かない。 (UIStackViewを使用しているのは、Storyboard上で「ログインせずに使用する」ボタンを定義しているのでそれに簡単に揃えたかったからです) 答え: コードでもAutoLayoutを使う! ViewController.swift // ボタンの生成 let authorizationButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white) // コードでAutoLayoutするためのおまじない(意味を知りたい方は調べてください) authorizationButton.translatesAutoresizingMaskIntoConstraints = false // Storyboardで作成済みのUIStackViewに追加 self.signInBtnStackView.insertArrangedSubview(authorizationButton, at: 0) // サイズ比率のAutoLayoutを記述(この場合は11:2の割合になる) authorizationButton.widthAnchor.constraint(equalTo: authorizationButton.heightAnchor, multiplier: 11/2).isActive = true このようにコードでボタンのサイズのAutoLayoutを設定することで、無事UIStackViewを使用したまま「Sign in with Apple」ボタンの大きさを変えることができました! Googleの方はデフォルトでドロップシャドウが設定されているので幅が少し小さくなっています。次はこれのサイズ調整も考えなければ... おしまい 不安定なことは多いですが、やはりビルドしなくても見た目がわかるStoryboardはいいですね。できる限りStoryboardで部品を配置したいものです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Xcode + Swift でiPhone用 地図アプリ。(23日目) 完成?

今日やった事 ・ストーリーボードでボタンを3つ作成(種別) ・ボタンのクリックイベント作成 ・ボタンクリック後、MySQLサーバーへデータ送信 ・データ送信結果をダイアログで表示(OK or ERROR) コード ViewController.swift //クリックイベント(3個) @IBAction func Trash01(_ sender: Any) { print("[DBG] : TRASH 01" ) HttpGET(data:"0") } @IBAction func Trash02(_ sender: Any) { print("[DBG] : TRASH 02" ) HttpGET(data:"1") } @IBAction func Trash03(_ sender: Any) { print("[DBG] : TRASH 03" ) HttpGET(data:"2") } ... // Http func HttpGET(data:String){ let data:String = DateTime() + ","+data+"," + longitude + "," + latitude // BASIC AUTH let username = "(ID)" let password = "(PASS)" let session = URLSession.shared guard let url = URL(string: "(URL)/hoge.php?huga="+data) else { return } var request = URLRequest(url: url) request.httpMethod = "GET" guard let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8) else { return } let credential = credentialData.base64EncodedString(options: []) let basicData = "Basic \(credential)" request.setValue(basicData, forHTTPHeaderField: "Authorization") session.dataTask(with: request) { data, urlresponse, error in if let error = error { self.ErrorDialog(data:"送信 ERROR") return } }.resume() self.ErrorDialog(data:"送信 成功") } //確認ダイアログ func ErrorDialog(data:String){ let alert: UIAlertController = UIAlertController(title: "確認", message: data, preferredStyle: UIAlertController.Style.alert) let confirmAction: UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler:{ (action: UIAlertAction!) -> Void in }) alert.addAction(confirmAction) present(alert, animated: true, completion: nil) } 完成 作成したボタンをタップする事で、WEB上のMySQLサーバへデータの記録が出来ることを確認。 失敗した場合は、ダイアログで確認できるようにしています。 最小限の機能のみですが、一応、完成。 Kotlinと比較すると、swiftの方は、初日の環境作成を含めて3日程で、比較的楽に作る事が出来ました。 後は、ボタンに画像を表示したり、設定画面を作るなど…。 これまでの流れで、[androidアプリ]、[iPhoneアプリ]、[MySQLサーバ]、[WEBサイト]と一通り全部作り終えたので、一旦、これで閉めるかもしれません。 参考サイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】CollectionViewで(横)スクロールする度に位置を自動調整させる方法

はじめに collectionViewで画像を横スクロールで表示させる実装をした際、中途半端な位置で止まった時に自動スクロールで位置調整させたくてたまりませんでした。 こんなイメージ やってみました。 環境 Xcode 13.2.1 Swift 5.5.2 実装 メイン画面 ViewController final class LessonImageViewController: UIViewController { @IBOutlet weak var customCollectionView: UICollectionView! // スクロール開始した位置 var scrollBeginingPoint: CGPoint! // スクロールした方向 var scrollDirection: Bool = true override func viewDidLoad() { super.viewDidLoad() customCollectionView.delegate = self customCollectionView.dataSource = self customCollectionView.register(UINib(nibName: "ImageCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ImageCell") let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal customCollectionView.setCollectionViewLayout(layout, animated: true) } } extension LessonImageViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return lessonsArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let customCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) guard let imageCell = customCell as? ImageCollectionViewCell else { return customCell } // カスタムセルを作ってセル自体にインデックスを持たせます imageCell.setLessonData(lesson: viewModel.lessonsArray.value[indexPath.row], row: indexPath.row) return imageCell } // 画面のスクロールを開始した位置を保存 func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { scrollBeginingPoint = scrollView.contentOffset; } // 画面をスクロールした瞬間の位置を保存 func scrollViewDidScroll(_ scrollView: UIScrollView) { let currentPoint = scrollView.contentOffset; // スクロール開始位置とスクロールした直後の位置を比較 // スクロールした方向を判定 if scrollBeginingPoint.x < currentPoint.x { scrollDirection = true } else { scrollDirection = false } } // 画面のスクロールが止まったら自動スクロールさせる func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { // 画面に表示されているセルを取得 let cells = customCollectionView.visibleCells var indexArray: [Int] = [] var indexRow: Int? // カスタムセルに持たせておいたインデックスを取得しておく for cell in cells { guard let safeCell = cell as? ImageCollectionViewCell else { return } indexArray.append(safeCell.row ?? 0) } guard !indexArray.isEmpty else { return } // スクロール方向によって取得したインデックス番号の最大値or最小値を取得する if scrollDirection { indexRow = indexArray.max() } else {    indexRow = indexArray.min() } // 最後に取得したインデックスまで自動スクロールさせる customCollectionView.scrollToItem(at: IndexPath(item: indexRow ?? 0, section: 0), at: .centeredHorizontally, animated: true) } } カスタムセルの実装 CollectionViewCell class ImageCollectionViewCell: UICollectionViewCell { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var lessonImageView: UIImageView! var lesson: Lesson? var row: Int? func setLessonData(lesson: Lesson, row: Int) { self.lesson = lesson titleLabel.text = lesson.title lessonImageView.contentMode = .scaleAspectFit lessonImageView.image = lesson.getImage() // セルのインデックスを持たせておく self.row = row } } 横スクロールの方向(右or左)を判定 スクロールが止まった時に画面に表示されているセルのインデックスを取得 スクロール方向により適当なセルへ自動スクロールさせる ということでした。 感想 無事、自動で位置調整させたくてたまらない欲求がおさまりました。 もっと簡単に実装できるような気もしていましたが、 やりたかったことが実現できたので良しとしました。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NavigationBarの色を固定する方法

今回はNavigationBarの色について記述します。 Xcodeを13.1にアップデートしてから画面をスクロールするとNavigationBarの色が変化してしまうなってずっと悩んでいたものがやっと解決されとてもうれしいです。。 NavigationBarの色を固定していない NavigationBarの色を固定 解決方法!! 以下gif画像のように動作する。 色の設定をしたいStoryBoardにてNavigationBarを選択 [ユーティリティエリア]>>[NavigationBar]の[Appearances]の[Standard]と[Scroll Edge]にチェックをいれる →→すると[Standard Appearance]と[Scroll Edge Appearance]を設定できるようになる それぞれのBackGroundを好みの色に設定する 完了!! ( 画質悪くてすいません、m(_ _)m ) 役割解説 Appearance Standard Scroll Edge 状態 画面がスクロールされてるとき 画面がスクロールされてないとき イメージ おまけ いじっていたらグラデーションができたのでおまけでつけておきます 色の設定をしたいStoryBoardにてNavigationBarを選択 [ユーティリティエリア]>>[NavigationBar]の[Appearances]の[Scroll Edge]にチェックをいれる [Scroll Edge Appearances]の[BackGround]を[default]に設定する [NavigationBar]自体の[BackGround]を好みの色に設定する [実行結果]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Swift, iOSでGraphQLクライアントを導入する

この記事について iOSアプリでGraphQLサーバにアクセスするためのクライアントを実装するための導入を書きます。サーバ機能ではなく、クライアント機能の説明です。 Swift iOS15 Xcode13 なお、サーバ側の実装については【Go言語】はじめてのGraphQLサーバ実装 | gqlgenも記述したのでご覧下さい。 手順 Apollo-iosパッケージのインストール GraphQLのライブラリではおなじみのapolloを利用します。 XcodeのFile -> Add Packages を開き、apollo-iosを検索してインストールします。 スキーマ定義のダウンロード apolloコマンドのインストール apolloコマンドがインストールされていなければインストールします。インストールにはnode.jsやJavaScriptでの開発でパッケージ管理でおなじみのnpmを使います。(npmコマンドのインストールについては割愛させていただきます。) $ npm install -g apollo スキーマのダウンロード GraphQLサーバに向けて下記のコマンドを実行します。ここではschema.jsonファイルにスキーマ定義が全て記述されます。 $ apollo schema:download --endpoint=http://localhost:8080/graphql schema.json schema.jsonをXcodeプロジェクト内に設置します。デフォルトではビルドターゲットのアプリの階層直下に保存します。つまり*.xcodeprojファイルがある階層の次のディレクトリです。(Assets.xcassetsディレクトリがある階層に保存) ビルド設定の追加 ここが難所です。Apollo公式ドキュメントの「Adding a code generation build step」と併せてご覧下さい。 ビルドターゲット・アプリケーションのBuildPhasesを開きます。 BuildPhasesで「+」ボタンをクリックし「New Run Script Phase」を選びます。「Run Script」が追加されます。 追加された「Run Script」を「Generate Apollo GraphQL API」に名称変更します。 タイトル部分をクリックすると変更できます。 あくまでも開発者が見て分かりやすい名前にします。 「Generate Apollo GraphQL API」を既存項目の「Compile Sources」の上に移動します。 Apollo公式ドキュメントの「Swift Package Manager Run Script」を画面のフォームに貼り付けます。 (必要に応じて)最後の行でschema.jsonのパスを編集します。 (必要に応じて)最後の行で生成されるSwiftファイルのパスを編集します。 ビルド 通常通りアプリケーションをビルドします。API.swiftが生成されます。ただ、プロジェクト内では管理されていないのでfinder等でソースコードを確認したら、Xcodeのプロジェクトに追加します。 エラー ここで下記のようなエラーに遭遇しました。こちらの投稿によるとapollo-iosの0.9.5バージョンではSwift5にきちんと対応できていないことが原因のようです。「Update Package」をして0.50.0にしたら解消しました。(2022年1月11日現在) Cannot convert parent type 'EnumeratedSequence<[Key]>' to expected type 'EnumeratedSequence<IndexingIterator<Array<Key>>>' クエリの実行 https://www.apollographql.com/docs/ios/initialization/#basic-client-creationにて基本的なクライントの実装方法が説明されています。シングルトン設計にしていますね。 GqlDriver.swift import Foundation import Apollo class GqlDriver { static let shared = ApiDriver() private (set) lazy var apollo = ApolloClient(url: URL(string: "http://localhost:8080/graphql")!) } 上記のGraphQL APIドライバクラスに対して下記のようにクエリを実行します。fetch関数でサーバに問い合わせています。引数のqueryには先ほどの自動生成で作成されたGraphQLクエリを指定します。 func func1() { GqlDriver.shared.apollo.fetch(query: UserQuery(id:"VXNlcjox")) { result in switch result { case .success(let r): // r に戻り値が含まれるので処理を書く。 case .failure(let e): print("\(e)") } } } 参考・関連文献 https://www.apollographql.com/docs/ios/installation/ https://www.apollographql.com/docs/ios/downloading-schema/ https://www.apollographql.com/docs/devtools/cli/ https://community.apollographql.com/t/error-building-swift-project-after-installing-apollo-ios-client/2308/2 https://www.apollographql.com/docs/ios/initialization/#basic-client-creation https://blog.spacemarket.com/code/graphql-on-swift-by-apollo-ios/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む