アイスタイル Advent Calendar 2022 21日目を担当させて頂きます、こたちゃんです
はじめに
私は、3週間ほど前からiOSのアプリチームで研修をしている新卒のエンジニアになります👩💻
普段は主にバックエンドエンジニアしてます!
これまで、Swiftに一度も触れたことがなかったのですが、学んで2週間ほどで、、なんだこれ、、楽しすぎる!!!と恋をしてしまうような体験をしてしまったため
触れたことないいんだけどやってみるか!
といった人を増やすべく、この記事を書こうと思いました
「ボタンを押したらおみくじの結果が表示される」という初心者の方でも作れるようなアプリを
チュートリアルのような形式で作成していこうと思います
作成するアプリ
仕様・要件
- おみくじを引く画面
- おみくじアプリのタイトル、「引く」ボタンがある
- 「引く」ボタンを押下すると結果画面へ遷移する
- 結果画面
- 結果画面では大吉、中吉、小吉、吉、末吉、凶、大凶の7種類の結果が表示される
- 結果は画像とテキストの両方が表示され、内容が一致している
- 「戻る」ボタンでおみくじを引く画面へ戻る
- 「もう一度」ボタンで結果の表示が変わる
このアプリ開発で学べること
- 画面遷移(モーダル遷移)
- 遷移元に戻る処理
- UIImage
- UIImageView
- 配列
- 乱数の生成
実装手順
0.アプリの雛形作成
1.スタート画面の作成
2.もう一つの画面を追加する
3.画面遷移の設定
4.戻るボタンの作成
5.ランダムに表示させるコントローラの書き方
6.画像を表示する
7.もう一度ボタンを押すと再度抽選される
0. アプリの雛形作成
xcodeを立ち上げると
「Welcome to Xcode」と表示されおり、その下に三つの項目があります。
今回は新しいiOSアプリのプロジェクトを作成するため、下記を選択してください。
iOSのAppを選択して「Next」ボタンを押してください。
次にProduct Nameを入力します。
今回はおみくじのアプリですので「OmikujiApp」とします。
InterfaceがStoryboard
かどうか確認した後に「Next」ボタンを押してください。
ここまででアプリの雛形作成が完了しました。
さっそく、実装を始めていきます。
1. スタート画面の作成
まずは左側の並んでいるファイルツリーの中からMainを開いて下さい。
真っ白のiPhoneがでてくるはずです。
① iPhoneの上にView Controller
と書かれた枠があるのでクリック
② +ボタンをクリック
③ Label
をクリックしたままドラッグ&ドロップ
真っ白なiPhoneにドラッグ&ドロップするとLabel
が追加されます。
Label
の文字を変更しましょう。
右上に並んでいるメニューの右から3つ目をクリックするとTextを入力するフィールドがあります。
TextをLabelから「おみくじアプリ」に変更してください。
他のやり方として
要素を直接ダブルクリックして変更もできます。
続いて、おみくじを引くためのボタンを設置していきます。
先ほどのLabel
と同じようにドラッグ&ドロップして設置してください。
先ほどと同じようにテキストを変更したいと思います。
右上に並んでいるメニューの右から3つ目をクリックするとTitleを入力するフィールドがあります。
Titleをbutton
から「引く」に設定してください。
2. もう一つの画面を追加する
右上の+ボタンから
View Conntrollerを検索し、作業中のiPhoneの横にドラッグ&ドロップをします。
下記の画像のように横に並べれたら大丈夫です。
クリックしたまま動かすと移動させることが出来ます。
左側のファイルが並んでいるところで、右クリックして「NewFile」を選択
Swift File
を選択し「Next」ボタンを押してください。
結果を表示する画面になりますので
ResultViewController
という命名にして「Create」ボタンを押します。
続いて、Storyboard
と繋げていきます。
右側のiPhoneを選択してください。
① 右上に並んでいるメニューの右から4つ目をクリックするとCustom Class
がでてきます。
② Classがプルダウンで選択できますので先ほど作成したResultViewController
を選択します。
上記は複数の画面を一つのStoryboardで管理していく方法です。
それ以外にも1つの画面に1つのStoryboardを用意する方法もあります。
今回はそちらの説明は省略させて頂きます。
気になった方はぜひ、ググってみてください!
3. 画面遷移の設定
続いて、画面を遷移するための設定を行います。
今回は「引く」ボタンをおすと結果の画面に移動するように設定します。
「引く」ボタンを選択します。
Controlキーを押しながら、「引く」ボタンを遷移の画面までドラッグします。
遷移先の画面で離すと以下のようなメニューが出てくるので、
今回は「Present Modally」を選択してください。
すると画面の間に矢印が出てきます。
この矢印はセグエ
と言い、画面遷移の流れを示します。
セグエが表示されているかどうか確認して下さい。
右側のiPhoneの上部分も変化していることがわかると思います。
ここまでの作業で「引く」ボタンをクリックすると
モーダルでの遷移を行うところまで実装することができました。
4. 戻るボタンの作成
遷移先にもボタンを設置していきます。
Button
を選択し、ドラッグ&ドロップします。
右上に並んでいるメニューの右から3つ目をクリックするとTitleを変更させることができます。
button
から「戻る」に変更します。
「戻る」ボタンのコントローラーの記述
今回は「戻る」ボタンですので、関数名をbackButtonAction
と名付けます。
@IBAction private func backButtonAction() {
dismiss(animated: true)
}
@IBAction
とは、
ユーザーがUIに対して行うアクションを関連付けるために利用する関数につける属性です。
dismiss()
とは、
ViewController自身を破棄するメソッドです。
遷移元の上に上書きしていた遷移先画面が破棄された結果、元の画面に戻ります。
@animated
とは、
ボタンを押下した際のアニメーションの有無を設定できます。
続いて、Storyboard
と繋げていきます。
画面の右上にある下記のアイコンを押すと2画面になります。
繋げるために2画面にしてください。
2画面にした後、
左側にResultViewController
右側にStoryboard を配置します。
逆でも問題ありません。
backButtonActionをControlキーを押しながら、「戻る」ボタンの画面までドラッグします。
Touch Up Inside
を選択します。
Touch Up Insideは、
ボタンを押したあとにボタンの近くで指を離したときにメソッドが呼び出されるものです。
ここまでで以下の画面遷移ができるようになりました。
・「引く」を押したら結果の画面に遷移する
・「戻る」を押したらおみくじを引くの画面に遷移する
5. ランダムに表示させるコントローラの書き方
続いて「引く」ボタンを押すと
ランダムに大吉、中吉、小吉、吉、末吉、凶、大凶の7種類のいずれかを結果として表示させていきます。
+ボタンからLabelを選択、Labelをクリックしたままドラッグ&ドロップします。
次にコントローラーに記述していきます。
下記のように定義します。
@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部分にあたります。
続いて表示するための文字列を配列にしていきます。
private let omikujiText: [String] = [
"大吉",
"中吉",
"小吉",
"吉",
"末吉",
"凶",
"大凶"
]
配列では整数から文字列、クラスなどのあらゆる種類のデータ形式を格納することが可能です。
配列を作成する方法は簡単で、
以下のように(コンマ)で区切ったリストを[]で囲むだけで作成することができます。
書き方(型指定なし)
let 配列名 = [値1, 値2, 値3, ……]
書き方(型指定):
let 配列名: [Int] = [値1, 値2, 値3, ……]
ランダムにラベルの文言を変える関数を作成していきます。
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と繋げていきます。
下記のように◉に変化していれば繋がっています。
ここまででコードは以下のようになっています。
//
// 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
を探してドラッグ&ドロップをします。
Content Mode
は「Aspect Fit」にしておきます。
Aspect Fitと指定しておくと、縦横の比率を保ったまま収まるサイズに拡大縮小してくれます。
縦横比で余った分は空白になります。
そのため、画像が伸びて見えたり比率がおかしく見えるなどが起きないようにしてくれます。
アスペクト比などについて詳しいqiitaの記事がありましたので参考にしてみてください。
今回使用する画像はどんな画像でも良いです。
大吉 フリー素材🔍 などで検索して保存した画像をAssets
に格納してください。
Assetsに格納した画像は
Scalesを「Single Scale」に設定します。
次にコントローラーに記述していきます。
まずは、下記のように定義します。 resultImage
と命名しました。
@IBOutlet private weak var resultImage: UIImageView!
先ほどのラベルと同じように配列を作成していきます。
今回はAssets
に格納した画像のファイル名を記述して下さい。
private let omikujiImage: [String] = [
"daikichi",
"chuukichi",
"syoukichi",
"kichi",
"suekichi",
"kyou",
"daikyou"
]
下記に追記していきます。
今回はtextではなく.imageで画像の変更を行うことができます。
そして画像をrandomIntからランダムに選択しています。
private func setOmikujiResult() {
let randomInt = Int.random(in: 0..<7)
resultLabel.text = String(omikujiText[randomInt])
+ resultImage.image = UIImage(named: omikujiImage[randomInt])
}
Storyboardと繋げていきます。
下記のように◉に変化していれば繋がっています。
7. もう一度ボタンを押すと再度抽選される
まずは、「もう一度」ボタンの作成をします。
ドラッグ&ドロップでボタンを設置した後、Button
から「もう一度」に変更します。
今回は、「もう一度」ボタンを押した際にアクションが起きるため
againButtonAction
と命名します。
下記はボタンが押された瞬間、 setOmikujiResult()
が呼び出されるようにしています。
@IBAction private func againButtonAction() {
setOmikujiResult()
}
記述ができたら、ドラッグ&ドロップでボタンとアクションを紐付けます。
下記のボタンが◉になれば大丈夫です。
完成コード
//
// 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
// 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()
画像の表示 ... UIImage、UIImageView
配列 ... let 配列名: [Int] = [値1, 値2, 値3, ……]
乱数の生成 ... Int.random(in: 0..<7)
swiftを触り始めて2週間の初心者が作成しているため拙い説明だったかもしれませんが...
これをきっかけにiOSに興味を持ってくださる方が増えると嬉しいです
みなさま、素敵なクリスマス、年末をお過ごし下さい
参考文献
【チャレンジ】