Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

iOSAdvent Calendar 2023

Day 13

Alert表示のメソッドをViewControllerから切り出す方法

Posted at

ViewControllerから別のファイルにAlert表示のメソッドを切り出す際の問題点

複数箇所で同じアラート文を複数の画面で使用するため、ViewControllerから別のファイルにAlert文を切り出そうとしたら、下記のようなエラーが起こりました!

AlertMaker.swift
struct AlertMaker {
    func showAPIErrorAlert() {
        let alert = UIAlertController(title: "エラー", message: "通信に失敗しました。", preferredStyle: .alert)
        let retryAction = UIAlertAction(title: "リトライ", style: .default, handler: {(action) -> Void in
            print("OK")

        })
        let cancelAction = UIAlertAction(title: "キャンセル", style: .default, handler: {(action) -> Void in
            print("キャンセル")
        })
        alert.addAction(retryAction)
        alert.addAction(cancelAction)
//🟥 エラー:Cannot find 'present' in scope
        present(alert, animated: true, completion: nil)
    }
}

なぜ上記のように🟥Cannot find 'present' in scopeというエラーが起こったのか?

func present(
    _ viewControllerToPresent: UIViewController,
    animated flag: Bool,
    completion: (() -> Void)? = nil
)

presentメソッドはclassであるUIViewControllerのメソッドであるため、UIViewController内でしか使用できません。

解決方法:Alert表示のメソッドを切り出す!

AlertMaker.swift
struct AlertMaker {
    func showAPIErrorAlert(didTapRetry: @escaping () -> Void) -> UIAlertController {
        let alert = UIAlertController(title: "エラー", message: "通信に失敗しました。", preferredStyle: .alert)
        let action = UIAlertAction(title: "リトライ", style: .default, handler: {(action) -> Void in
            didTapRetry()
        })
        alert.addAction(action)
        return alert
    }
}

先ほど見たようにpresentメソッドはUIViewControllerで使用する必要があるため、AlertMakerファイルの戻り値として、UIAlertControllerを戻すようにした。

okyoViewController.swift
class TokyoViewController: UIViewController {
    private let latitude = "35.689753"
    private let longitude = "139.691731"
    let apiClient = APIClient()
    let alertMaker = AlertMaker()

    @IBOutlet weak var weatherLabel: UILabel!
    @IBOutlet weak var prefectureLabel: UILabel!

    @IBAction func tappedTokyo(_ sender: UIButton) {
        showWetherView()
    }
    func showWetherView() {
        apiClient.getWeatherFromAPI(
            latitude: latitude,
            longitude: longitude,
            success: { description, cityName in
                DispatchQueue.main.async {
                    self.weatherLabel.text = description
                    self.prefectureLabel.text = cityName
                }
            },
            failure: {
                DispatchQueue.main.async {
                //🟩UIAlertControllerの戻り値を受け取る!
                    let alert = self.alertMaker.showAPIErrorAlert {
                        self.showWetherView()
                    }
                    self.present(alert, animated: true, completion: nil)
                }
            }
        )
    }
}

UIViewController側で、AlertMakerファイルから🟩UIAlertControllerの戻り値を受け取りalert定数に代入し、presentメソッドのみをUIViewController側で使用することができました!

参考文献

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?