ビルドするとコンソールは
viewDidLoad①
↓
viewDidLoad②
↓
collectionViewメソッド
↓
fetchUserメソッド
の順番で呼ばれております。
質問が2点あります。
①なぜcollectionViewメソッドがfetchUserメソッドがより早く呼ばれるのか。
②collectionViewメソッドはどこから呼び出されているのか。
①について自分の考え
viewDidLoad内でfetchUserメソッドが呼ばれているためfetchUserメソッドの実行の方がより早いと思ってしまう。
よろしくお願い致します。
import UIKit private let cellIdentifier = "ProfileCell" private let headerIdentifier = "ProfileHeader" class ProfileController: UICollectionViewController { // MARK: - Properties var user: User? { didSet { collectionView.reloadData(); print("userプロパティ")} } // MARK: - Lifecyzcle override func viewDidLoad() { super.viewDidLoad() print("viewDidLoad①") configureCollectionView() fetchUser() print("viewDidLoad②") } // MARK: - API func fetchUser() { UserService.fetchUser { (user) in --------------------------------------------------------- print("fetchUserメソッド") --------------------------------------------------------- self.user = user self.navigationItem.title = user.username } } // MARK: - Helpers func configureCollectionView() { collectionView.backgroundColor = .white collectionView.register(ProfileCell.self, forCellWithReuseIdentifier: cellIdentifier) collectionView.register(ProfileHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifier) } } // データソース // MARK: - UICollectionViewDataSource extension ProfileController { override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { --------------------------------------------------------- print("collectionViewメソッド") --------------------------------------------------------- return 9 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ProfileCell return cell } //ヘッダー override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as! ProfileHeader if let user = user { header.viewModel = ProfileHeaderViewModel(user: user) } else { print("ユーザーがまだいません") } return header } }
fetchUser の中身を 2 つに分けて考える必要があります。一つは UserService.fetchUser(completion:) の呼び出し、もう一つはそれに対する引数であるクロージャ { (user) in 〜 }。fetchUser が呼ばれると、UserService.fetchUser(completion:) が実行されてユーザーの情報の取得が開始されますが、おそらくネットワーク通信が絡んで実際に情報が取得されるまでには時間がかかります。が、UserService.fetchUser(completion:) は情報の取得を待たずにいったん終了して、情報が取得された後にクロージャ { (user) in 〜 } の中身が実行されます。このため、print("fetchUserメソッド") の表示が最後となります。
hoshi-takanoriさん、
ここに書かれているコメントは、ズバり回答そのものですから、回答本文に書かれたほうが良いと思います。
「質問への追記」に書かれたコメントは意外と読まない回答者が多いため、せっかく適切なコメントをされても見られない可能性が高いと思います(で、実際間違った回答がついてしまいました)。
hoshi-takanoriさん、ありがとうございます。
https://teratail.com/questions/320084
こちらの質問の(2)と繋がっていて、双方とも理解が進みました。
大変恐縮ですが、hoshi-takanoriさんの回答を転記して自己解決として転記させて頂きます。
次回から回答いただける際は、「回答」でいただけると自己解決とする心苦しさがないです!笑
TsukubaDepotさん、コメントありがとうございます。
いや、自己解決でもいいと思いますよ。
たぶん、hoshi-takanoriさんは自己解決を案に促しているのだと思います。
質問がオープン(未解決)のまま残されるよりも、「具体的に何がわかったのか」記載して自己解決される方が何倍も有益だと思います。
たしかにそうかもしれないですね。
この質問で自己解決を書いているときに新しい気付きや疑問が生まれました。
・なぜ結果取得を待たずして一旦fetchUser()は終了するのか
です。
また整理して、理解できなかったら別途質問を開きます。
以下はコメント上の質問になってしまい恐縮なんですが、
②collectionViewメソッドはどこから呼び出されているのか。
はどこになるのでしょうか。
>以下はコメント上の質問になってしまい恐縮なんですが、
>②collectionViewメソッドはどこから呼び出されているのか。
下記の回答にコメントしましたので、そちらをご参照ください。
回答2件
あなたの回答
tips
プレビュー