20201121のiOSに関する記事は9件です。

[iOS/Swift]Alamofire を利用したアプリ実装(郵便番号検索アプリを例に)

書くこと

Alamofire を利用した API 呼び出しを利用してアプリを実装する

書いた理由

Alamofire を利用した API 呼び出し方法を忘れた時に確認する

参考にした記事

標準とAlamofireでAPIコール処理を書き比べてみる(Swift)

上記記事に紹介されていたコードに、UIを実装した
(すごくわかりやすい記事です)

前提条件

  1. テキストフィールド、ボタンおよび検索結果を表示するラベルは Main.storyboard で設定
  2. 上記要素は、ViewController.swift に紐づけている
  3. CocoaPods を利用して Alamofire はすでに導入済である

アプリの機能

テキストフィールドに郵便番号を入力し[Seach]ボタンをタップすると、ラベル(水色)にその郵便番号に対応する住所を表示する。

・郵便番号が入力されていない場合や入力した文字が7桁ではない場合はアラートを表示する

コード例

AddressModel.swift
// このコードは参考にした記事より流用した
struct AddressModel: Decodable {
    var results: [Result]

    struct Result: Decodable {
        var address1: String
        var address2: String
        var address3: String
        var kana1: String
        var kana2: String
        var kana3: String
    }
}
ViewController.swift
import UIKit
import Alamofire

class ViewController: UIViewController {

    private var addresses: AddressModel?

    @IBOutlet weak var zipCodeTextField: UITextField!
    @IBOutlet weak var seachButton: UIButton!
    @IBOutlet weak var resultLabel: UILabel!

    @IBAction func tapSeachButton(_ sender: Any) {
        self.getAddress(zipCode: zipCodeTextField.text)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    private func getAddress(zipCode: String?) {
        self.validate(zipCode: zipCode)

        let baseUrl = "https://zipcloud.ibsnet.co.jp/api/"
        let searchUrl = "\(baseUrl)search"
        let parameters: [String: Any] = ["zipcode": zipCode!]
        let headers: HTTPHeaders = ["Content-Type": "application/json"]

        self.requestAPI(url: searchUrl, parameters: parameters, headers: headers)
    }

    private enum ErrorType:String {
        case zipCodeNil = "郵便番号が確認できません"
        case zipCodeBrank = "郵便番号を入力してください"
        case zipCodeLengthNot7 = "郵便番号は7桁で入力してください"
    }

    private func validate(zipCode: String?){
        guard let zipCode = zipCode else { self.showAlert(error: .zipCodeNil); return }
        if zipCode == "" { self.showAlert(error: .zipCodeBrank); return }
        if zipCode.lengthOfBytes(using: .utf8) != 7 { self.showAlert(error: .zipCodeLengthNot7); return }
    }

    private func showAlert(error: ErrorType) {
        let alert = UIAlertController(title: "検索に失敗しました", message: error.rawValue, preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)
        self.present(alert, animated: true, completion: nil)
    }

    private func requestAPI(url:String,parameters:[String:Any],headers:HTTPHeaders) {
        AF.request(url, method: .get, parameters: parameters, encoding: URLEncoding(destination: .queryString), headers: headers).responseJSON { response in
            guard let data = response.data else { return }
            do {
                try self.parse(data: data)
            } catch let error {
                print("Error: \(error)")
                self.showError()
            }
        }
    }

    private func parse(data:Data) throws {
        self.addresses = try JSONDecoder().decode(AddressModel.self, from: data)
        if let address = self.addresses {
            self.show(result: "\(address.results[0].address1) \(address.results[0].address2) \(address.results[0].address3)")
        }
    }

    private func show(result:String){
        resultLabel.text = result
    }

    private func showError(){
        resultLabel.text = "検索結果が取得できませんでした"
    }
}

参考資料

Alamofire
標準とAlamofireでAPIコール処理を書き比べてみる(Swift)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

非同期処理について

同期処理と非同期処理の基本

同期処理とは

あるタスクを順番に実行する方式で、そのタスクが実行されている間は他のタスクが中断される

非同期処理とは

ある処理を実行する間に他の処理を実行できる

DispatchQueueとは

GCD(Grand Central Dispatch)の一部
DispatchQueueないにタスクを詰めると非同期で実行してくれる

DispatchQueue自体には、
Serial、Concurrent、mainの3種類がある。

DispatchQueue.main

OS側で作成済みなので呼び出すだけ。
1つだけ存在。
直列処理タイプ。
UI表示系タスクはここで行わないと動かない。

viewController.swift
let mainQueue = DispatchQueue.main

DispatchQueue.Global

OS側で作成済みなので呼び出すだけ。
5つ存在。(ただし、実質使えるのは4つ)
並列処理タイプ。
用途を指定して呼出し。

viewController.swift
// UserInteractiveタイプ
let grobalQueue = DispatchQueue.global(qos: .userInteractive)

sync

viewController.swift
dispatchQueue.sync {
    print("同期")
}

async

viewController.swift
dispatchQueue.async {
    print("非同期")
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

同期、非同期処理について

同期処理と非同期処理の基本

同期処理とは

あるタスクを順番に実行する方式で、そのタスクが実行されている間は他のタスクが中断される

非同期処理とは

ある処理を実行する間に他の処理を実行できる

DispatchQueueとは

GCD(Grand Central Dispatch)の一部
DispatchQueueないにタスクを詰めると非同期で実行してくれる

DispatchQueue自体には、
Serial、Concurrent、mainの3種類がある。

DispatchQueue.main

OS側で作成済みなので呼び出すだけ。
1つだけ存在。
直列処理タイプ。
UI表示系タスクはここで行わないと動かない。

viewController.swift
let mainQueue = DispatchQueue.main

DispatchQueue.Global

OS側で作成済みなので呼び出すだけ。
5つ存在。(ただし、実質使えるのは4つ)
並列処理タイプ。
用途を指定して呼出し。

viewController.swift
// UserInteractiveタイプ
let grobalQueue = DispatchQueue.global(qos: .userInteractive)

sync

viewController.swift
dispatchQueue.sync {
    print("同期")
}

async

viewController.swift
dispatchQueue.async {
    print("非同期")
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

キーボードタイプの種類とコード

はじめに

キーボードタイプの書き方や種類一旦ここにまとめようかなと思います。

定義

UIKeyboardTypeの定義をJump to Definition(コマンドキーを押しながら調べたいところをクリック)で調べてみました。
以下の通りです。

public enum UIKeyboardType : Int {


    case `default` = 0 // Default type for the current input method.

    case asciiCapable = 1 // Displays a keyboard which can enter ASCII characters

    case numbersAndPunctuation = 2 // Numbers and assorted punctuation.

    case URL = 3 // A type optimized for URL entry (shows . / .com prominently).

    case numberPad = 4 // A number pad with locale-appropriate digits (0-9, ۰-۹, ०-९, etc.). Suitable for PIN entry.

    case phonePad = 5 // A phone pad (1-9, *, 0, #, with letters under the numbers).

    case namePhonePad = 6 // A type optimized for entering a person's name or phone number.

    case emailAddress = 7 // A type optimized for multiple email address entry (shows space @ . prominently).

    @available(iOS 4.1, *)
    case decimalPad = 8 // A number pad with a decimal point.

    @available(iOS 5.0, *)
    case twitter = 9 // A type optimized for twitter text entry (easy access to @ #)

    @available(iOS 7.0, *)
    case webSearch = 10 // A default keyboard type with URL-oriented addition (shows space . prominently).

    @available(iOS 10.0, *)
    case asciiCapableNumberPad = 11 // A number pad (0-9) that will always be ASCII digits.


    public static var alphabet: UIKeyboardType { get } // Deprecated
}

種類

種類は合計13種類あるみたいです。

  • default
  • asciiCapable
  • numbersAndPunctuation
  • URL
  • numberPad
  • phonePad
  • namePhonePad
  • emailAddress
  • decimalPad
  • twitter
  • webSearch
  • asciiCapableNumberPad
  • alphabet

実装方法

TextFieldをアウトレットで接続して、viewDidLoadで表示のコードを書きます。
.以降を変更してそれぞれのキーボードタイプを見ていきます。

import UIKit

class ViewController: UIViewController {

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!
    @IBOutlet var textField6: UITextField!
    @IBOutlet var textField7: UITextField!
    @IBOutlet var textField8: UITextField!
    @IBOutlet var textField9: UITextField!
    @IBOutlet var textField10: UITextField!
    @IBOutlet var textField11: UITextField!
    @IBOutlet var textField12: UITextField!
    @IBOutlet var textField13: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.textField1.keyboardType = .default
        self.textField2.keyboardType = .asciiCapable
        self.textField3.keyboardType = .numbersAndPunctuation
        self.textField4.keyboardType = .URL
        self.textField5.keyboardType = .numberPad
        self.textField6.keyboardType = .phonePad
        self.textField7.keyboardType = .namePhonePad
        self.textField8.keyboardType = .emailAddress
        self.textField9.keyboardType = .decimalPad
        self.textField10.keyboardType = .twitter
        self.textField11.keyboardType = .webSearch
        self.textField12.keyboardType = .asciiCapableNumberPad
        self.textField13.keyboardType = .alphabet
    }
}

実装結果

① default
スクリーンショット 2020-11-21 17.33.32.png

② asciiCapable
スクリーンショット 2020-11-21 17.32.19.png

③ numbersAndPunctuation
スクリーンショット 2020-11-21 17.35.22.png

④ URL
スクリーンショット 2020-11-21 17.40.37.png

⑤ numberPad
スクリーンショット 2020-11-21 17.41.29.png

⑥ phonePad
スクリーンショット 2020-11-21 17.42.23.png

⑦ namePhonePad
スクリーンショット 2020-11-21 17.42.57.png

⑧ emailAddress
スクリーンショット 2020-11-21 17.43.44.png

⑨ decimalPad
スクリーンショット 2020-11-21 17.44.26.png

⑩ twitter
スクリーンショット 2020-11-21 17.45.00.png

⑪ webSearch
スクリーンショット 2020-11-21 17.45.42.png

⑫ asciiCapableNumberPad
スクリーンショット 2020-11-21 17.46.24.png

⑬ alphabet
スクリーンショット 2020-11-21 17.47.00.png

最後に

13種類もあるなんて知りませんでした。
状況に合わせて使いこなせるようにしたいですね!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Develop in Swift Data CollectionsでiOS開発を学ぶ (1): Lesson 1.2まで

※(1)とついてますが続くかは不明

Develop in Swift Data Collectionsとは

Appleが高校生や大学生向けに出している学習用教材に含まれる、勉強用のドキュメントです。

https://www.apple.com/tr/education/docs/develop-in-swift-curriculum-guide.pdf

スクリーンショット 2020-11-21 12.35.38.png

学生向け学習用カリキュラムがあり、そのカリキュラムの最終段階で学ぶ内容のようです。難しそうですが、まぁ現役のプログラマーならいけるでしょう(多分)。

この本を見つつ、iOS開発について学んでいく、という記事になります。基本は本を読んで、僕の記事はあくまで参考程度に見てもらえると良いと思います。

本自体はApple Booksから無料でダウンロードできます。

https://books.apple.com/jp/book/develop-in-swift-data-collections/id1511183970

前提知識・環境

もちろんMacが必要です。サンプルコードはXcode11のようですが、最新のM1搭載Mac上のXcode12でもサンプルコードは動きそうな気配がしてます(まだ全部のソースコードを動かしたわけではないですが)。

あた先ほど貼ったカリキュラム通り、Swfitの基本的な書き方とかは知っている前提の本になっていると思われます。

サンプルコードのダウンロード

8ページ目にサンプルコードをまとめたzipファイルへのリンクが貼ってあり、ここからダウンロードすることができます。

スクリーンショット 2020-11-21 15.28.16.png

すべてのレッスンのサンプルコードが含まれている、というわけではなさそうです。

やってみる

Unit 1: Tables And Persistence

章のタイトルが?って感じなのですが、この章を終えると情報の表示と変数、保存のUIを構築できるようになるようです。

“By the end of this unit, you'll be comfortable building many useful apps that display all kinds of information and that allow users to enter, edit, and save in-app information.”

抜粋:: Apple Education “Develop in Swift Data Collections”。 Apple Inc. - Education、2020年 Apple Books https://books.apple.com/jp/book/develop-in-swift-data-collections/id1511183970

Lesson 1.1: Protocols

プロトコル(他の言語で言うとinterface)の話がずっと続きます。いきなりプロトコルの話からはじまるのが結構ガチだなという気がしますが、iOSアプリ開発においてはすごい基礎的で重要なことなんでしょうね。

この本は、一通り読み終わった後、章末問題的なものが用意されています。

スクリーンショット 2020-11-21 12.47.06.png

いやーすごいですね。Apple Booksこんなこともできるんだ。

Lesson 1.2: App Anatomy and Life Cycle

アプリケーションのライフサイクルとAppDelegate/SceneDelegateの話が出てきます。

この節は実際にコードを組んでみるという実験(本ではLabと読んでいるようなので)があるのでやってみます。

実験はアプリケーションのライフサイクルの動きを観察するものです。雛形は本のサンプルコード集に含まれていないようなので、Xcodeで新しく作成します。

で、コードを記述していきます。

1. AppDlegateにカウンタ変数を追加

下記の2つのメソッドの呼び出し回数をカウントできるようにコードを追加します。最終的に下記のようになると思います。

  • application(_:didFinishLaunchingWithOptions:)
  • application(_:configurationForConnecting:options:)
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var launchCount = 0
    var configurationForConnectingCount = 0

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        launchCount += 1
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        configurationForConnectingCount += 1
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    }


}

2. ViewControllerに表示用のラベルを追加

Main.storyboardを開き、下記のようにラベルを追加していきます。

スクリーンショット 2020-11-21 14.59.15.png

普通にlabelを置いていっても良いと思いますし、StackView内に積んで行っても良いと思います。

僕はこのQiitaの記事を参考にVertical StackViewを配置して、その中にラベルを置いていきました。そしてAutoLayoutで上下左右を端っこにピン留め。

Main.storyboardを作った後は、ViewController.swiftにそれぞれのラベルをアウトレットとして繋いで行きます。アウトレットというのは、要するにStoryboard上のUIパーツへの参照です。

    @IBOutlet weak var didFinishLaunchingWithOptionsLabel: UILabel!
    @IBOutlet weak var configurationForConnectingLabel: UILabel!
    @IBOutlet weak var willConnectToLabel: UILabel!
    @IBOutlet weak var didBecomeActiveLabel: UILabel!
    @IBOutlet weak var willResignActiveLabel: UILabel!
    @IBOutlet weak var willEnterForegroundLabel: UILabel!
    @IBOutlet weak var didEnterBackgroundLabel: UILabel!

そして、それぞれのラベルに表示させるカウンタ変数を作成します。

    var willConnectToCount = 0
    var didBecomeActiveCount = 0
    var willResignActiveCount = 0
    var willEnterForegroundCount = 0
    var didEnterBackgroundCount = 0

3. AppDelegateの変数にViewControllerからアクセスする

SceneDelegateのカウンタ変数はViewController内にあるのですが、AppDelegateのカウンタ変数はAppDelegate内にあります(多分AppDelegateの方が生存期間が長いから?)

なので、それにアクセスできるようにする必要があります。

ViewControllerに下のように書けばアクセスできるようです。

    var appDelegate = (UIApplication.shared.delegate as! AppDelegate)

そして、それぞれのラベルを更新するupdateViewメソッドをViewControllerに作成します。

    func updateView() {
        didFinishLaunchingWithOptionsLabel.text = "didFinishLaunchingWithOptions called  \(appDelegate.launchCount) time(s)"
        configurationForConnectingLabel.text = "configurationForConnection called \(appDelegate.configurationForConnectingCount) time(s)"
        willConnectToLabel.text = "willConnectTo called \(willConnectToCount) time(s)"
        didBecomeActiveLabel.text = "didBecomeActive called \(didBecomeActiveCount) time(s)"
        willResignActiveLabel.text = "willResiginActive called \(willResignActiveCount) time(s)"
        willEnterForegroundLabel.text = "willEnterForeground called \(willEnterForegroundCount) time(s)"
        didEnterBackgroundLabel.text = "didEnterBackground called \(didEnterBackgroundCount) time(s)"
    }

4. SceneDelegateからViewControllerにアクセスする

SceneDelegateのカウンタ変数はViewControllerにあるので、SceneDelegateからViewControllerのカウンタ変数を操作する必要があります。

メンバ変数としてviewControllerを宣言し、

var viewController: ViewController?

willConnectToでwindowから取れば良いようです。

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
...        
        viewController = window?.rootViewController as? ViewController
...
    }

5. SceneDelegateでカウンタ変数を更新する

viewControllerにSceneDelegateからアクセスできるようになったので、カウンタ変数を更新します。最終的にSceneDelegateは下記のようになると思います。

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    var viewController: ViewController?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }

        viewController = window?.rootViewController as? ViewController
        viewController?.willConnectToCount += 1
    }

    func sceneDidDisconnect(_ scene: UIScene) {
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        viewController?.didBecomeActiveCount += 1
        viewController?.updateView()
    }

    func sceneWillResignActive(_ scene: UIScene) {
        viewController?.willResignActiveCount += 1
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        viewController?.willEnterForegroundCount += 1
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        viewController?.didEnterBackgroundCount += 1
    }
}

6. updateViewを適切なタイミングで呼ぶ

カウンタ変数を更新しても、それをviewに反映させないと見ることはできません。

ViewControllerのupdateViewを適切なタイミングで呼ぶ必要があります。

SceneDelegateでは、先ほど貼ったコードで必要なタイミングで呼び出せています。あとはViewControllerのviewDidLoadで呼べばオッケーです。

最終的にViewControllerは下記のようになると思います。

class ViewController: UIViewController {

    @IBOutlet weak var didFinishLaunchingWithOptionsLabel: UILabel!
    @IBOutlet weak var configurationForConnectingLabel: UILabel!
    @IBOutlet weak var willConnectToLabel: UILabel!
    @IBOutlet weak var didBecomeActiveLabel: UILabel!
    @IBOutlet weak var willResignActiveLabel: UILabel!
    @IBOutlet weak var willEnterForegroundLabel: UILabel!
    @IBOutlet weak var didEnterBackgroundLabel: UILabel!

    var willConnectToCount = 0
    var didBecomeActiveCount = 0
    var willResignActiveCount = 0
    var willEnterForegroundCount = 0
    var didEnterBackgroundCount = 0

    var appDelegate = (UIApplication.shared.delegate as! AppDelegate)

    override func viewDidLoad() {
        super.viewDidLoad()
         updateView()
    }

    func updateView() {
        didFinishLaunchingWithOptionsLabel.text = "didFinishLaunchingWithOptions called  \(appDelegate.launchCount) time(s)"
        configurationForConnectingLabel.text = "configurationForConnection called \(appDelegate.configurationForConnectingCount) time(s)"
        willConnectToLabel.text = "willConnectTo called \(willConnectToCount) time(s)"
        didBecomeActiveLabel.text = "didBecomeActive called \(didBecomeActiveCount) time(s)"
        willResignActiveLabel.text = "willResiginActive called \(willResignActiveCount) time(s)"
        willEnterForegroundLabel.text = "willEnterForeground called \(willEnterForegroundCount) time(s)"
        didEnterBackgroundLabel.text = "didEnterBackground called \(didEnterBackgroundCount) time(s)"
    }
}

7. 動作確認

ここまでやったら動くようになっているので、実際にシミュレーターで動かします。動かした時の様子をgifで貼っておきます。

Nov-21-2020 15-16-59.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Xcode, Pods ProjectName.debug.xcconfig unable to open file.に対する対応方法

はじめに

Githubからcloneしたプロジェクトの実行を試みた際にProjectName.debug.xcconfig unable to open fileというエラーに遭遇したため備忘録をかねて記録として残したいと思います。

以下のようにしていただければ解決できるかと存じます。

solved
pod deintegrate
pod install

今回参考にした記事です。
より詳細に記載がりますので、よろしければご参照ください。
https://stackoverflow.com/questions/55558984/xcode-pods-projectname-debug-xcconfig-unable-to-open-file-wrong-directory

ご参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

iOSアプリでOSで提供する機能のUI言語の切り替え

OSで提供する機能を呼び出す際にデフォルトのプロジェクト設定ではUIが英語表示になる。
日本語で表示させるためにはプロジェクトの設定からLocalizationにJapaneseを追加する。

スクリーンショット 2020-11-21 17.43.25.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUI】TabViewとListの実装とViewのフォルダ管理

はじめに

SwiftUIでTabViewを作成し、それぞれのTabItemごとにViewを作る。
HomeViewにはListを表示し、前回作成したカード型のRowを呼び出すことを目的とする。

UIのデザインはcakesのnote風のデザインを参考にViewを作ります。

今後は今回作成したカードに前回までに実装した地図と都道府県市町村名を表示できるようにし、Firebaseで更新できるようにすることが目的です。
前回までの記事は以下を参考ください。

参考記事
【SwiftUi】経過時間の表示とListViewのセルデザイン

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

TabViewの作成とフォルダ管理

TabBarView_swift.png

それぞれのViewはグループにまとめます。
大本のルートになるViewはContentViewです。
ContentViewの記載内容は以下のとおりです。

import SwiftUI

struct ContentView: View {

    var body: some View {
        // TabBarViewの呼び出し
        TabBarView()
    }

}

ContentviewではTabBarViewの呼び出しのみを行い、TabBarViewではHomeやSearch、Post、Info、AccountのそれぞれのViewを呼び出します。

import SwiftUI

struct TabBarView: View {
    var body: some View {

        TabView {
            // HomeView
            NavigationView{
                // HomeViewの呼び出し
                Home()
                    .navigationBarTitle("ホーム", displayMode: .inline)
            }.tabItem {
                Image(systemName: "house.fill")
                    .font(.title)
                Text("ホーム")
            }

            // SearchView
            NavigationView{
                // SearchViewの呼び出し
                Search()
                    .navigationBarTitle("みつける", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "map.fill")
                    .font(.title)
                Text("マップ")
            }


            // PostView
            Text("Post")
                .tabItem {
                    Image(systemName: "plus.circle.fill")
                        .font(.title)
                    Text("詠む")
                }

            // InfomationView
            NavigationView{
                // InfoViewの呼び出し
                Info()
                    .navigationBarTitle("おしらせ", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "info.circle.fill")
                    .font(.title)
                Text("おしらせ")
            }

            // AccountView
            NavigationView{
                // AccountViewの呼び出し
                Account()
                    .navigationBarTitle("アカウント", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "person.fill")
                    .font(.title)
                Text("アカウント")
            }
        }
        .accentColor(Color("pinkColor"))

    }
}

HomeViewにListを実装する

Home_swift.png

前回記事で作成したRowを呼び出します。

参考記事
【SwiftUi】経過時間の表示とListViewのセルデザイン

本来なら、ここのRow部分はFirebaseからデータベースを呼び出し更新できるように実装しますが、まだ実装できていないため、今回は同じ記事を出力しています。
また、今後はスクロールした際に記事を自動でロードできるようにする予定です。
今回はListの出力の様子のみ確認します。

import SwiftUI

struct Home: View {
    var body: some View {
        List {
            ForEach(0..<8){_ in
                ContentRowView()
                    .listRowInsets(EdgeInsets())
            }
        }
    }
}

iPhone_11_–_14_2.png

Simulatorで確認したところ、スムーズにスクロールができました。
また、navigationBarTitleもスクロールしても表示され続けているため、意図したとおりに実装できました。

できれば、ListのRowごとに出力されるボーターの左側の余白を消したいけど、実装の仕方を見つけられなかったため、次回修正します。

今後実装予定のもの

・HomeViewのList内のRow部分をFireBaseから更新できるようにする。
・Search、Post、Info、AccountのそれぞれのViewを実装する。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUi】TabViewとListの実装とViewのフォルダ管理

はじめに

SwiftUIでTabViewを作成し、それぞれのTabItemごとにViewを作る。
HomeViewにはListを表示し、前回作成したカード型のRowを呼び出すことを目的とする。

UIのデザインはcakesのnote風のデザインを参考にViewを作ります。

今後は今回作成したカードに前回までに実装した地図と都道府県市町村名を表示できるようにし、Firebaseで更新できるようにすることが目的です。
前回までの記事は以下を参考ください。

参考記事
【SwiftUi】経過時間の表示とListViewのセルデザイン

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

TabViewの作成とフォルダ管理

TabBarView_swift.png

それぞれのViewはグループにまとめます。
大本のルートになるViewはContentViewです。
ContentViewの記載内容は以下のとおりです。

import SwiftUI

struct ContentView: View {

    var body: some View {
        // TabBarViewの呼び出し
        TabBarView()
    }

}

ContentviewではTabBarViewの呼び出しのみを行い、TabBarViewではHomeやSearch、Post、Info、AccountのそれぞれのViewを呼び出します。

import SwiftUI

struct TabBarView: View {
    var body: some View {

        TabView {
            // HomeView
            NavigationView{
                // HomeViewの呼び出し
                Home()
                    .navigationBarTitle("ホーム", displayMode: .inline)
            }.tabItem {
                Image(systemName: "house.fill")
                    .font(.title)
                Text("ホーム")
            }

            // SearchView
            NavigationView{
                // SearchViewの呼び出し
                Search()
                    .navigationBarTitle("みつける", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "map.fill")
                    .font(.title)
                Text("マップ")
            }


            // PostView
            Text("Post")
                .tabItem {
                    Image(systemName: "plus.circle.fill")
                        .font(.title)
                    Text("詠む")
                }

            // InfomationView
            NavigationView{
                // InfoViewの呼び出し
                Info()
                    .navigationBarTitle("おしらせ", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "info.circle.fill")
                    .font(.title)
                Text("おしらせ")
            }

            // AccountView
            NavigationView{
                // AccountViewの呼び出し
                Account()
                    .navigationBarTitle("アカウント", displayMode: .inline)
            }
            .tabItem {
                Image(systemName: "person.fill")
                    .font(.title)
                Text("アカウント")
            }
        }
        .accentColor(Color("pinkColor"))

    }
}

HomeViewにListを実装する

Home_swift.png

前回記事で作成したRowを呼び出します。

参考記事
【SwiftUi】経過時間の表示とListViewのセルデザイン

本来なら、ここのRow部分はFirebaseからデータベースを呼び出し更新できるように実装しますが、まだ実装できていないため、今回は同じ記事を出力しています。
また、今後はスクロールした際に記事を自動でロードできるようにする予定です。
今回はListの出力の様子のみ確認します。

import SwiftUI

struct Home: View {
    var body: some View {
        List {
            ForEach(0..<8){_ in
                ContentRowView()
                    .listRowInsets(EdgeInsets())
            }
        }
    }
}

iPhone_11_–_14_2.png

Simulatorで確認したところ、スムーズにスクロールができました。
また、navigationBarTitleもスクロールしても表示され続けているため、意図したとおりに実装できました。

できれば、ListのRowごとに出力されるボーターの左側の余白を消したいけど、実装の仕方を見つけられなかったため、次回修正します。

今後実装予定のもの

・HomeViewのList内のRow部分をFireBaseから更新できるようにする。
・Search、Post、Info、AccountのそれぞれのViewを実装する。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む