Help us understand the problem. What is going on with this article?

全世界の福袋だいすきガールに贈る!福袋わくわくアプリ

More than 1 year has passed since last update.

[前書き]もうすぐお正月ですね

こんにちは、もうクソアプリ2も7日目!12月あっという間ですね、どうぞよろしくお願いします。

さて!!もうすぐお正月ですね!(ん、気が早い、、、、??まあ、どうせクリスマス去ったらあっという間にお正月くるやん、、)
お正月に楽しみにしていることと言えば〜〜〜福袋ですよね!!!
限りある予算の中でどれを買うか考える時間は楽しいし、中身を開ける瞬間は本当にドキドキしちゃうお正月の1大イベントです。けど、福袋ってすぐ売り切れるしで。めちゃくちゃ情報戦ですよね。
今回はTableViewやUserDefaultsなどの基本的な機能を復習しつつ、福袋戦争をサポートするアプリを作って見ました。その過程で色々詰まったところやこだわったところ、新しく知ったことなどなど書いていきます。

[今回作ったもの]福袋アプリ

今回作ったものは、全世界の福袋大好きガールに贈る!福袋わくわくアプリ「HappyBag」を作ってみました。多分1年の中でわずか数週間しか使わないであろうかつ、ユーザー層もかなり限られているかつ、福袋というたった1つのコンテンツのために作ったクソアプリです。買う福袋をチェックするtodoアプリみたいな感じです。
sai.gif

[開発環境]

Xcode ver10.1
Swift 4
macOSHighSierra ver10.13

[リスト機能]TableViewを使って福袋の情報を管理しよう!

  • UserDefaultsに欲しい福袋の名前/発売される日付を配列で保存し、TableViewに表示
  • 購入したらチェックを付けられる

実装の流れ

ListViewController[リストを確認する方の画面]

  • 必要な変数を宣言 リストの内容を保存するようの配列
ListViewController
    let Userdefaults:UserDefaults = UserDefaults.standard
    var nameHyoziArray:[String] = []//福袋名を表示する配列
    var dateHyoziArray:[String] = []//購入予定を表示する配列
    var isEdit:Bool!
    var cellNumber:Int!
  • viewDidLoadとviewWillAppearで今あるリストの中身を読み込む
ListViewController
override func viewDidLoad() {
        super.viewDidLoad()
        table.dataSource = self
        table.delegate = self
        if Userdefaults.object(forKey: "nameFukubukuro") != nil{
            nameHyoziArray = Userdefaults.object(forKey: "nameFukubukuro") as! [String]
        }
        if Userdefaults.object(forKey: "dateFukubukuro") != nil{
            dateHyoziArray = Userdefaults.object(forKey: "dateFukubukuro") as! [String]
        }
        table.reloadData()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        isEdit = false
        table.dataSource = self
        table.delegate = self
        if Userdefaults.object(forKey: "nameFukubukuro") != nil{
            nameHyoziArray = Userdefaults.object(forKey: "nameFukubukuro") as! [String]
        }
        if Userdefaults.object(forKey: "dateFukubukuro") != nil{
            dateHyoziArray = Userdefaults.object(forKey: "dateFukubukuro") as! [String]
        }
        table.reloadData()
    }
  • セルの設定と新規登録画面に行く際の画面遷移
ListViewController
//セルの数を設定するメソッド
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return nameHyoziArray.count
    }

    //IDのついたセルを呼び出すメソッド
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
        cell?.textLabel?.text = nameHyoziArray[indexPath.row]
        return cell!
    }

    //セルがタップされた時
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
        cellNumber = indexPath.row
        isEdit = true
        self.performSegue(withIdentifier: "toSaveViewController", sender: (Any).self)
        table.deselectRow(at:indexPath, animated: true)

    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let saveviewcontroller:SaveViewController = segue.destination as! SaveViewController
        saveviewcontroller.cellNumber = cellNumber
        saveviewcontroller.isEdit = isEdit
    }

SaveViewController[リストを登録する方の画面]

  • 必要な変数を宣言 リストの内容を保存するようの配列
SaveViewController
var userdefaults:UserDefaults = UserDefaults.standard
    @IBOutlet var nameTextField:UITextField!//福袋の名前を記入する
    @IBOutlet var dateTextField:UITextField!//日付を記入する
    @IBOutlet var moneyTextField:UITextField!
    var dateArray:[String] = []
    var nameArray:[String] = []
    var moneyArray:[Int] = []
    var cellNumber:Int!//何番目のcell
    var isEdit: Bool!//編集中か否か
  • 既にあるリストを編集する場合はデータを読み込む
SaveViewController
override func viewDidLoad() {
        super.viewDidLoad()
        if userdefaults.object(forKey: "nameFukubukuro") != nil{
            nameArray = userdefaults.object(forKey: "nameFukubukuro") as! [String]
            nameTextField.text = userdefaults.object(forKey: "nameFukubukuro") as? String
        }
        if userdefaults.object(forKey: "dateFukubukuro") != nil{
            dateArray = userdefaults.object(forKey: "dateFukubukuro") as! [String]
            dateTextField.text = userdefaults.object(forKey: "dateFukubukuro") as? String
        }
        if userdefaults.object(forKey: "moneyFukubukuro") != nil{
            moneyArray = userdefaults.object(forKey: "moneyFukubukuro") as! [Int]
            moneyTextField.text = userdefaults.object(forKey: "moneyFukubukuro") as? String
        }


        if isEdit == true{
            if userdefaults.object(forKey: "nameFukubukuro") != nil{
                nameTextField.text = nameArray[cellNumber]
            }

            if userdefaults.object(forKey: "dateFukubukuro") != nil{
                dateTextField.text = dateArray[cellNumber]
            }

        }
    }

- セーブボタンを押したら保存される

SaveViewController
@IBAction func saveButton(){
        if nameTextField.text != ""{
            if isEdit == false{
                nameArray.append(nameTextField.text!)
                userdefaults.set(nameArray, forKey: "nameFukubukuro")
                dateArray.append(dateTextField.text!)
                userdefaults.set(dateArray, forKey: "dateFukubukuro")
                moneyArray.append(Int(moneyTextField.text!)!)
                userdefaults.set(moneyArray, forKey: "moneyFukubukuro")
                self.dismiss(animated: true, completion: nil)
                print("nameArray:",nameArray.count)
            }else{
                nameArray[cellNumber] = nameTextField.text!
                userdefaults.set(nameArray, forKey: "nameFukubukuro")
                dateArray[cellNumber] = dateTextField.text!//nullを吐く可能性
                userdefaults.set(dateArray, forKey: "dateFukubukuro")
                isEdit = false
                self.dismiss(animated: true, completion: nil)
            }
        }
    }

新しい学び

delegate,datasource

デフォルトのViewControllerには、tableViewCellの高さや、内容を決めることができないから、この2行を追加しています。

dequeueReusableCell

UITableViewはCellを使い回しています。
こちらは、同じCellIdentifierが付いているもので再利用できるものがあれば返してくれるメソッド。
この写真では"Cell"というIdentifierがついたものを探してくれています。

カスタムフォントが反映されない場合

下記記事を読んで対応しました。CopyBundleResourcesにフォントファイルが追加されていないことが原因でした。
https://shigu493.com/2018-02-12-【swift3】xcodeでカスタムフォントが反映されないと/

チェックボックスの実装

下記記事を参考にしました。画像を用意してボタンをクリックされたら画像が変わるようにしました。各セルごとに反応するようにUITableViewを継承したクラスを用意しました

TableViewCell
class TableViewCell: UITableViewCell {
    let checkImage = UIImage(named: "ok_check.png")
    let nonCheckImage = UIImage(named: "non_check.png")
    @IBOutlet var todoButton: UIButton!
    override func awakeFromNib() {
        super.awakeFromNib()

    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    @IBAction func imageDidTap(_ sender: UIButton) {
        todoButton.setImage(checkImage, for: .normal)

    }

https://qiita.com/bohebohechan/items

[後書き]え?ただのTodoアプリやんけって?

開発日記になってしまいました、本当にすみませええええん。
通知機能が付けたかったけど間に合いませんでした笑 いつか追記します。。
福袋が楽しみな人がより幸せになれますように、、、!
明日以降もどんなクソアプリが登場するか楽しみです〜〜!
何か間違っていることがあればコメント待っています。

[参考記事]

こちらの記事を参考にさせていただきました。ありがとうございます。

tableViewの使い方

https://pg-happy.jp/swift-tableview-tableviewcell.html

UIDatePicker

https://www.egao-inc.co.jp/programming/swift_uidatepicker/

UITableViewのdelegate・datasourceについて

http://programming-beginner-memo.com/?p=15

UISegmentedControl

http://www.swift-study.com/uisegmentedcontrol-basic/

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away