LoginSignup
29
21

More than 1 year has passed since last update.

Swift初心者によるSwift初心者のためのアプリ開発

Last updated at Posted at 2022-12-20

アイスタイル Advent Calendar 2022 21日目を担当させて頂きます、こたちゃんです:santa_tone1::gift:

はじめに

私は、3週間ほど前からiOSのアプリチームで研修をしている新卒のエンジニアになります👩‍💻
普段は主にバックエンドエンジニアしてます!

これまで、Swiftに一度も触れたことがなかったのですが、学んで2週間ほどで、、なんだこれ、、楽しすぎる!!!と恋をしてしまうような体験:heart_eyes:をしてしまったため
触れたことないいんだけどやってみるか!
といった人を増やすべく、この記事を書こうと思いました:sunny:

「ボタンを押したらおみくじの結果が表示される」という初心者の方でも作れるようなアプリを
チュートリアルのような形式で作成していこうと思います:muscle_tone1:

作成するアプリ

mojikyo45_640-2.gif

仕様・要件

  • おみくじを引く画面
    • おみくじアプリのタイトル、「引く」ボタンがある
    • 「引く」ボタンを押下すると結果画面へ遷移する
  • 結果画面
    • 結果画面では大吉、中吉、小吉、吉、末吉、凶、大凶の7種類の結果が表示される
    • 結果は画像とテキストの両方が表示され、内容が一致している
    • 「戻る」ボタンでおみくじを引く画面へ戻る
    • 「もう一度」ボタンで結果の表示が変わる

このアプリ開発で学べること

  • 画面遷移(モーダル遷移)
  • 遷移元に戻る処理
  • UIImage
  • UIImageView
  • 配列
  • 乱数の生成

実装手順

0.アプリの雛形作成
1.スタート画面の作成
2.もう一つの画面を追加する
3.画面遷移の設定
4.戻るボタンの作成
5.ランダムに表示させるコントローラの書き方
6.画像を表示する
7.もう一度ボタンを押すと再度抽選される

0. アプリの雛形作成

xcodeを立ち上げると
「Welcome to Xcode」と表示されおり、その下に三つの項目があります。

今回は新しいiOSアプリのプロジェクトを作成するため、下記を選択してください。
スクリーンショット 2022-12-14 16.49.56.png

iOSのAppを選択して「Next」ボタンを押してください。
スクリーンショット 2022-12-15 19.03.33.png

次にProduct Nameを入力します。
今回はおみくじのアプリですので「OmikujiApp」とします。
InterfaceがStoryboardかどうか確認した後に「Next」ボタンを押してください。
スクリーンショット 2022-12-20 13.08.40.png

ここまででアプリの雛形作成が完了しました。
さっそく、実装を始めていきます。

1. スタート画面の作成

まずは左側の並んでいるファイルツリーの中からMainを開いて下さい。
真っ白のiPhoneがでてくるはずです。

① iPhoneの上にView Controllerと書かれた枠があるのでクリック
② +ボタンをクリック
Labelをクリックしたままドラッグ&ドロップ

スクリーンショット 2022-12-16 11.30.02.png

真っ白なiPhoneにドラッグ&ドロップするとLabelが追加されます。
スクリーンショット 2022-12-16 11.30.02.png
Labelの文字を変更しましょう。
右上に並んでいるメニューの右から3つ目をクリックするとTextを入力するフィールドがあります。
TextをLabelから「おみくじアプリ」に変更してください。

他のやり方として
要素を直接ダブルクリックして変更もできます。

スクリーンショット 2022-12-16 11.40.14.png

続いて、おみくじを引くためのボタンを設置していきます。
先ほどのLabelと同じようにドラッグ&ドロップして設置してください。

スクリーンショット 2022-12-16 11.42.36.png
以下のようになっていれば大丈夫です。
mojikyo45_640-2.gif

先ほどと同じようにテキストを変更したいと思います。
右上に並んでいるメニューの右から3つ目をクリックするとTitleを入力するフィールドがあります。
Titleをbuttonから「引く」に設定してください。
スクリーンショット 2022-12-16 11.43.17.png

2. もう一つの画面を追加する

右上の+ボタンから
View Conntrollerを検索し、作業中のiPhoneの横にドラッグ&ドロップをします。
スクリーンショット 2022-12-16 11.49.25.png

下記の画像のように横に並べれたら大丈夫です。

クリックしたまま動かすと移動させることが出来ます。

スクリーンショット 2022-12-16 11.52.35.png

左側のファイルが並んでいるところで、右クリックして「NewFile」を選択

Swift Fileを選択し「Next」ボタンを押してください。
スクリーンショット 2022-12-16 11.54.05.png
結果を表示する画面になりますので
ResultViewControllerという命名にして「Create」ボタンを押します。

続いて、Storyboardと繋げていきます。
右側のiPhoneを選択してください。

① 右上に並んでいるメニューの右から4つ目をクリックするとCustom Classがでてきます。
② Classがプルダウンで選択できますので先ほど作成したResultViewControllerを選択します。
スクリーンショット 2022-12-16 11.59.54.png

上記は複数の画面を一つのStoryboardで管理していく方法です。
それ以外にも1つの画面に1つのStoryboardを用意する方法もあります。
今回はそちらの説明は省略させて頂きます。
気になった方はぜひ、ググってみてください!

3. 画面遷移の設定

続いて、画面を遷移するための設定を行います。
今回は「引く」ボタンをおすと結果の画面に移動するように設定します。

「引く」ボタンを選択します。
Controlキーを押しながら、「引く」ボタンを遷移の画面までドラッグします。
遷移先の画面で離すと以下のようなメニューが出てくるので、
今回は「Present Modally」を選択してください。
スクリーンショット 2022-12-16 12.12.15.png

すると画面の間に矢印が出てきます。
この矢印はセグエと言い、画面遷移の流れを示します。
セグエが表示されているかどうか確認して下さい。
右側のiPhoneの上部分も変化していることがわかると思います。
スクリーンショット 2022-12-16 12.12.26.png
ここまでの作業で「引く」ボタンをクリックすると
モーダルでの遷移を行うところまで実装することができました。

4. 戻るボタンの作成

遷移先にもボタンを設置していきます。
Buttonを選択し、ドラッグ&ドロップします。
スクリーンショット 2022-12-16 12.16.55.png

右上に並んでいるメニューの右から3つ目をクリックするとTitleを変更させることができます。
buttonから「戻る」に変更します。
スクリーンショット 2022-12-16 12.18.24.png

「戻る」ボタンのコントローラーの記述

今回は「戻る」ボタンですので、関数名をbackButtonActionと名付けます。

ResultViewController.swift
@IBAction private func backButtonAction() {
    dismiss(animated: true)
}

@IBActionとは、
ユーザーがUIに対して行うアクションを関連付けるために利用する関数につける属性です。

dismiss()とは、
ViewController自身を破棄するメソッドです。
遷移元の上に上書きしていた遷移先画面が破棄された結果、元の画面に戻ります。

@animatedとは、
ボタンを押下した際のアニメーションの有無を設定できます。

続いて、Storyboardと繋げていきます。
画面の右上にある下記のアイコンを押すと2画面になります。
繋げるために2画面にしてください。
スクリーンショット 2022-12-16 12.32.09.png

2画面にした後、
左側にResultViewController
右側にStoryboard を配置します。

逆でも問題ありません。

backButtonActionをControlキーを押しながら、「戻る」ボタンの画面までドラッグします。
スクリーンショット 2022-12-16 12.27.49.png

Touch Up Insideを選択します。
Touch Up Insideは、
ボタンを押したあとにボタンの近くで指を離したときにメソッドが呼び出されるものです。

正しく繋がっている場合は下記のように表示されます。
スクリーンショット 2022-12-16 12.28.07.png

ここまでで以下の画面遷移ができるようになりました。

・「引く」を押したら結果の画面に遷移する
・「戻る」を押したらおみくじを引くの画面に遷移する

5. ランダムに表示させるコントローラの書き方

続いて「引く」ボタンを押すと
ランダムに大吉、中吉、小吉、吉、末吉、凶、大凶の7種類のいずれかを結果として表示させていきます。

+ボタンからLabelを選択、Labelをクリックしたままドラッグ&ドロップします。
スクリーンショット 2022-12-20 0.29.27.png

次にコントローラーに記述していきます。
下記のように定義します。

ResultViewController.swift
@IBOutlet private weak var resultLabel: UILabel!

一つずつ簡単に説明します。
@IBOutlet
IBとはInterface Builderの略でつまりStroyBoardのことを指します。
@IBOutletとはStoryBoardに配置された部品をViewController内で扱うための接続を行います。

private
この部品の公開範囲です。
この部品は今編集しているViewController以外では呼び出されることがないのでprivateにしています。

weak
弱参照の意味です。

var label:
よく見るSwiftの変数の宣言と同じです。
ViewController内ではStoryBoard内に配置された部品を変数として扱います。
変数なので名前は自由に変えられます。 例 var numberLabel

UILabel!
よく見るSwiftの型宣言と同じです。var hoge: IntのInt部分にあたります。

続いて表示するための文字列を配列にしていきます。

ResultViewController.swift
private let omikujiText: [String] = [
    "大吉",
    "中吉",
    "小吉",
    "吉",
    "末吉",
    "凶",
    "大凶"
]

配列では整数から文字列、クラスなどのあらゆる種類のデータ形式を格納することが可能です。
配列を作成する方法は簡単で、
以下のように(コンマ)で区切ったリストを[]で囲むだけで作成することができます。

書き方型指定なし
let 配列名 = [値1, 値2, 値3, ……]
書き方型指定):
let 配列名: [Int] =  [値1, 値2, 値3, ……]

ランダムにラベルの文言を変える関数を作成していきます。

ResultViewController.swift
private func setOmikujiResult() {
    let randomInt = Int.random(in: 0..<7)
    resultLabel.text = String(omikujiText[randomInt])
}

分解して説明していきます。

関数は以下のように定義します。
privateは先ほども出てきたように公開範囲を限定します。
関数をよびだす時は関数名()

private func 関数名() {
}

Swiftでランダムな数字を生成するには独自メソッドが用意されています。
下記のように指定するとランダムな数字を返してくれます。
今回は配列に要素が7つあるため下記のように指定しています。

Int.random(in: 0..<7) // 0〜6まででランダムな数字(整数)を返す

先ほど定義したresultLabelに.textとするとUILabelのtextを変更することができます。
String()で型を文字列と指定しています。
omikujiText[randomInt]は配列[ランダムな数値]となっており
omikujiText[0]の場合、大吉が代入されます。

resultLabel.text = String(omikujiText[randomInt])

先ほど作成した関数を下記でsetOmikujiResult()と呼び出します。
viewDidLoad()はViewControllerの保持しているviewにアクセスしたときに呼び出されます。

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

Storyboardと繋げていきます。
下記のように◉に変化していれば繋がっています。
スクリーンショット 2022-12-20 1.18.43.png

確認として下記のようになっていれば大丈夫です。
スクリーンショット 2022-12-20 1.22.01.png

ここまででコードは以下のようになっています。

ResultViewController.swift
//
//  ResultViewController.swift
//  OmikujiApp
//
//

import UIKit

final class ResultViewController: UIViewController {
    
    @IBOutlet private weak var resultLabel: UILabel!
    
    private let omikujiText: [String] = [
        "大吉",
        "中吉",
        "小吉",
        "吉",
        "末吉",
        "凶",
        "大凶"
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        setOmikujiResult()
    }
    
    @IBAction private func backButtonAction() {
        dismiss(animated: true)
    }

    private func setOmikujiResult() {
        let randomInt = Int.random(in: 0..<7)
        resultLabel.text = String(omikujiText[randomInt])
    }
}

6. 画像を表示する

次におみくじの結果を画像で表示する設定を行なっていきます。

右上の+ボタンからImage Viewを探してドラッグ&ドロップをします。
スクリーンショット 2022-12-20 1.23.54.png

Content Modeは「Aspect Fit」にしておきます。
Aspect Fitと指定しておくと、縦横の比率を保ったまま収まるサイズに拡大縮小してくれます。
縦横比で余った分は空白になります。
そのため、画像が伸びて見えたり比率がおかしく見えるなどが起きないようにしてくれます。
スクリーンショット 2022-12-20 2.22.01.png

アスペクト比などについて詳しいqiitaの記事がありましたので参考にしてみてください。

今回使用する画像はどんな画像でも良いです。
大吉 フリー素材🔍 などで検索して保存した画像をAssetsに格納してください。
スクリーンショット 2022-12-20 1.26.46.png

Assetsに格納した画像は
Scalesを「Single Scale」に設定します。
スクリーンショット 2022-12-16 12.38.51.png

次にコントローラーに記述していきます。
まずは、下記のように定義します。 resultImageと命名しました。

ResultViewController.swift
@IBOutlet private weak var resultImage: UIImageView!

先ほどのラベルと同じように配列を作成していきます。
今回はAssetsに格納した画像のファイル名を記述して下さい。

ResultViewController.swift
private let omikujiImage: [String] = [
    "daikichi",
    "chuukichi",
    "syoukichi",
    "kichi",
    "suekichi",
    "kyou",
    "daikyou"
]

下記に追記していきます。
今回はtextではなく.imageで画像の変更を行うことができます。
そして画像をrandomIntからランダムに選択しています。

ResultViewController.swift
private func setOmikujiResult() {
    let randomInt = Int.random(in: 0..<7)
    resultLabel.text = String(omikujiText[randomInt])
+   resultImage.image = UIImage(named: omikujiImage[randomInt])
}

Storyboardと繋げていきます。
下記のように◉に変化していれば繋がっています。
スクリーンショット 2022-12-20 2.19.41.png

確認として下記のようになっていれば大丈夫です。
スクリーンショット 2022-12-20 1.37.53.png

7. もう一度ボタンを押すと再度抽選される

まずは、「もう一度」ボタンの作成をします。
ドラッグ&ドロップでボタンを設置した後、Buttonから「もう一度」に変更します。
スクリーンショット 2022-12-20 2.17.35.png

今回は、「もう一度」ボタンを押した際にアクションが起きるため
againButtonActionと命名します。
下記はボタンが押された瞬間、 setOmikujiResult()が呼び出されるようにしています。

@IBAction private func againButtonAction() {
    setOmikujiResult()
}

記述ができたら、ドラッグ&ドロップでボタンとアクションを紐付けます。
下記のボタンが◉になれば大丈夫です。
スクリーンショット 2022-12-20 2.18.41.png

完成コード

ResultViewController.swift
//
//  ResultViewController.swift
//  OmikujiApp
//

import UIKit

final class ResultViewController: UIViewController {
    
    @IBOutlet private weak var resultLabel: UILabel!
    @IBOutlet private weak var resultImage: UIImageView!
    
    private let omikujiText: [String] = [
        "大吉",
        "中吉",
        "小吉",
        "吉",
        "末吉",
        "凶",
        "大凶"
    ]
    
    private let omikujiImage: [String] = [
        "daikichi",
        "chuukichi",
        "syoukichi",
        "kichi",
        "suekichi",
        "kyou",
        "daikyou"
    ]
  
    override func viewDidLoad() {
        super.viewDidLoad()
        setOmikujiResult()
    }
    
    @IBAction private func backButtonAction() {
        dismiss(animated: true)
    }
    
    @IBAction private func againButtonAction() {
        setOmikujiResult()
    }
    
    
    private func setOmikujiResult() {
        let randomInt = Int.random(in: 0..<7)
        resultLabel.text = String(omikujiText[randomInt])
        resultImage.image = UIImage(named: omikujiImage[randomInt])
    }
}

【チャレンジ】効果音を入れてみる

下記は効果音を入れたverのコードになります。
ぜひ、チャレンジした後に確認してみて下さい!

ResultViewController.swift
//
//  ResultViewController.swift
//  OmikujiApp
//

import UIKit
+ import AVFoundation

final class ResultViewController: UIViewController {
    
    @IBOutlet private weak var resultLabel: UILabel!
    @IBOutlet private weak var resultImage: UIImageView!
    
    private let omikujiText: [String] = [
        "大吉",
        "中吉",
        "小吉",
        "吉",
        "末吉",
        "凶",
        "大凶"
    ]
    
    private let omikujiImage: [String] = [
        "daikichi",
        "chuukichi",
        "syoukichi",
        "kichi",
        "suekichi",
        "kyou",
        "daikyou"
    ]
    
+   private var player: AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        setOmikujiResult()
        playSoundEffect()
    }
    
    @IBAction private func backButtonAction() {
        dismiss(animated: true)
    }
    
    @IBAction private func againButtonAction() {
        setOmikujiResult()
        playSoundEffect()
    }
    
    
    private func setOmikujiResult() {
        let randomInt = Int.random(in: 0..<7)
        resultLabel.text = String(omikujiText[randomInt])
        resultImage.image = UIImage(named: omikujiImage[randomInt])
    }
    
+   private func playSoundEffect() {
+       if let soundURL = Bundle.main.url(forResource: "omikujiResultBgm", withExtension: "mp3") {
+           do {
+               player = try AVAudioPlayer(contentsOf: soundURL)
+               player?.play()
+           } catch {
+               print("error")
+           }
+       }
+   }
}

最後に

学んだ点のおさらいになります。

画面遷移(モーダル遷移) ... Present Modally
遷移元に戻る処理 ... dismiss()
画像の表示 ... UIImageUIImageView
配列 ... let 配列名: [Int] =  [値1, 値2, 値3, ……]
乱数の生成 ... Int.random(in: 0..<7)

swiftを触り始めて2週間の初心者が作成しているため拙い説明だったかもしれませんが...
これをきっかけにiOSに興味を持ってくださる方が増えると嬉しいです:relaxed:
みなさま、素敵なクリスマス、年末をお過ごし下さい:baby_tone1::snowflake:

参考文献

【チャレンジ】

29
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
21