質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.36%

シングルトンやユーザーディフォルトからのデータを関数にまとめる方法を教えてください

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 235

sssaqj

score 6

アプリ画面

シングルトンやユーザーディフォルトからのデータを関数にまとたい

タイマーマネージャーのシングルトンを持ったピッカービューで時間を設定するタイマーを作っています。時間を扱うために合計時間を時間、分、秒へと分解する箇所が複数あり冗長だなと思うので関数に処理をまとめたいと思います。
しかし、元の合計時間がシングルトンから引っぱってきたものと、ユーザーディフォルトからのものとが混在してうまくまとめる方法が考えられないのです。
どなたかご教示いただければ幸いです。

該当のソースコード

class TimerManager {
    static let shared = TimerManager()
    var timer : Timer?
    var setCount: Double? = nil
    var count = 0.0
    var remainCount: Double? = nil {
        didSet {
            onCountDidSet?(remainCount!)
        }
    }
    var onCountDidSet: ((_ count: Double) -> Void)? = nil

    func startCount() {
        if timer == nil {
            timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {
                timer in self.timerCount(timer)}
        }
    }        
    func stopCount() {
        count = 0.0
        pauseCount()
    }
    func pauseCount() {
        if let nowTimer = timer {
            if nowTimer.isValid == true {
                nowTimer.invalidate()                
            }
            self.timer = nil
        }
    }
    func timerCount(_ timer: Timer) {
        if let _ = UserDefaults.standard.object(forKey: "timer_value") as? Int {
            setCount = (UserDefaults.standard.object(forKey: "timer_value")) as? Double
        }
        count += 1.0
        if let set_count = setCount {
            remainCount = set_count - count
        }
        if let remain_count = remainCount {
            if remain_count <= 0.0 {                
                count = 0.0
                timer.invalidate()
                print("finish")
            }
        }
    }   
    var timer_status = "stop"    
    func timerStatus() {
        if timer == nil {
            timer_status = "stop"
        }
        else {
            timer_status = "counting"
        }
    }
}
---------------------------------------------
class ViewController: UIViewController {

    var alertController = UIAlertController()    
    @IBOutlet weak var countDownLabel: UILabel!    
    @IBAction func settingButtonAction(_ sender: Any) {
    }
    @IBAction func startButtonAction(_ sender: Any) {
        TimerManager.shared.startCount()
    }
    @IBAction func stopButtonAction(_ sender: Any) {
        TimerManager.shared.pauseCount()
    }
    var remain_counts = 0

    func remainCount() {
        TimerManager.shared.onCountDidSet = {
            remainCount in self.remain_counts = Int(remainCount)
            let hour = self.remain_counts / 3600
            let mHour = self.remain_counts % 3600
            let minites = mHour / 60
            let sMinites = mHour % 60
            let second = sMinites % 60
            print(hour,minites, second)
            self.countDownLabel.text = "残り \(hour) 時間  \(minites)\(second) 秒"
            if remainCount <= 0.0 {
                self.returnData()                
            }
        }
    }

    func returnData(){
            self.alert(title: "終了",
                       message: "終了です")
    }       
    func alert(title: String, message: String) {
        alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alertController, animated: true)               
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // 画面遷移時のタイマー作動/停止で表示を変える
        TimerManager.shared.timerStatus()
        let nowCount = TimerManager.shared.timer_status
        let presenceCount = TimerManager.shared.count

        // タイマー停止状態を判断
        if nowCount == "stop" {
            // カウンターもリセットされている(一時停止ではない)
            if presenceCount == 0.0 {
                if let time_value = UserDefaults.standard.object(forKey: "timer_value") as? Int {
                    print(time_value)
                    let hour = time_value / 3600
                    let mHour = time_value % 3600
                    let minites = mHour / 60
                    let sMinites = mHour % 60
                    let second = sMinites % 60
                    print(hour,minites, second)
                    countDownLabel.text = "残り \(hour) 時間  \(minites)\(second) 秒"
                } else {
                    // 一時停止なら残り時間を表示
                    remainCount()
                }
            }
            // タイマーが動いていれば残り時間を表示
        } else {
            remainCount()
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        remainCount()        
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        TimerManager.shared.onCountDidSet = nil
    }

    override func viewDidAppear(_ animated: Bool) {
        TimerManager.shared.timerStatus()
        let nowCount = TimerManager.shared.timer_status
        let presenceCount = TimerManager.shared.count

        if nowCount == "stop" {
            if presenceCount == 0.0 {
                if let time_value = UserDefaults.standard.object(forKey: "timer_value") as? Int {
                    print(time_value)
                    let hour = time_value / 3600
                    let mHour = time_value % 3600
                    let minites = mHour / 60
                    let sMinites = mHour % 60
                    let second = sMinites % 60
                    print(hour,minites, second)
                    countDownLabel.text = "残り \(hour) 時間  \(minites)\(second) 秒"
                    //                    countDownLabel.text = String(time_value)
                    //                    print(time_value)
                } else {
                    remainCount()
                }
            }
        } else {
            remainCount()
        }
    }
}

    func disassembly (value: Double) {
        let value = Int(value)
        let hour = value / 3600
        let mHour = value % 3600
        let minites = mHour / 60
        let sMinites = mHour % 60
        let second = sMinites % 60
        self.countDownLabel.text = "残り \(hour) 時間 \(minites)\(second) 秒"
    }

試したこと

最後のfunc disasseemblyのところのような関数を作ろうとしたのですが、シングルトンやユーザーディフォルトの理解が不十分であることはわかっています。色々なサイトから自分なりにまとめていったのですが、今の自分の頭では限界がきたためどなたかアドバイスいただければと思います。

補足情報(FW/ツールのバージョンなど)

x code 10.2.1   swift5.0.1   macOs Mojave 10.14.5

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • TsukubaDepot

    2020/04/16 07:03

    どこに詰まっているのかちょっとわかりにくい質問だと思います。

    具体的にどのようにまとめようとして、どのようなエラーがでたのか(あるいは、一応こうできたけど、ここが理解できない、など)といった、より具体的な問題点を挙げてもらった方がいいかと思います。

    キャンセル

  • sssaqj

    2020/04/16 07:21 編集

    let hour = self.remain_counts / 3600
    let mHour = self.remain_counts % 3600
    let minites = mHour / 60
    let sMinites = mHour % 60
    let second = sMinites % 60
    self.countDownLabel.text = "残り \(hour) 時間 \(minites) 分 \(second) 秒"
    というのがself.remain_countsやtime_valueを分解するという箇所が複数回出てきています。これらを1つの関数にして、使い回し短い表現にできたら良いなと思ったのです。
    しかし、
    TimerManager.shared.onCountDidSet = {
    remainCount in self.remain_counts = Int(remainCount)
    や今回長すぎて載せれなかった別画面のタイマーセッティング画面で作ったタイマー時間の変数を
    if let time_value = UserDefaults.standard.object(forKey: "timer_value") as? Int
    で取り出しているのですが、これらのために短くする方法を自分では見出せなかったのです。
    教本なんかによく同じような文章を繰り返していると短くした方が良いと書いているのを見かけるので、もっとうまく書く方法があるのじゃないかと思った次第です。

    キャンセル

  • TsukubaDepot

    2020/04/16 07:39

    考え方は間違っていないと思います。
    その考えを実行する一つの方法として、
    func disassembly (value: Double)
    という関数を一つ作り、それなりにまとまっていると思います。

    これを実際にご自身のプログラムに入れてみてコンパイルし、実行してみていますでしょうか。
    そうでなければ、まず試されてみてはいかがでしょうか。

    キャンセル

回答 1

check解決した方法

0

remainCount in self.remain_counts = Int(remainCount)
self.disassembly(value: self.remain_counts)

if let time_value = UserDefaults.standard.object(forKey: "timer_value") as? Int {
self.disassembly(value: time_value)

とすることで解決できました。アドバイスありがとうございました!!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/16 08:18

    悩むより、まずはやってみるのがいいかと思います。
    ただ、リファクタリング(コードの整理)を行うと、動いていたはずのコードが動かなくなるトラブルが発生することもあります。

    なので、同時にバージョン管理(Xcodeだと標準機能であります)の方法も抑えておくと安心です。

    キャンセル

  • 2020/04/16 08:36

    関数をようやく自分で書けるようになったような独学の初心者のためうまくいかなくなった時に途方に暮れてしまいます。バージョン管理、謎のGit repositoryも抑えに行きたいと思います。その辺がよくわからず、イチから打ち直してコピーするというバカなことをしていました。

    キャンセル

  • 2020/04/16 08:48

    いやいや、そんな卑下することはないと思いますよ。
    頑張った分報われると思いますから。
    少なくとも、今回の質問については方向性は間違っていないと思いますので、自信を持っていいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る