質問: "オペレーションから値の操作" return returnValue } else { print("FirstOperation cancel") } } } ``` しかし「override func main() -> String {」の行で、Method does not override any method from its superclassが出てしまいます。 これはmain()メソッドはオーバーライドしており、返り値を定義するとオバーライド元のメソッドと異なるメソッドだと判断されてしまい、エラーになったと仮定します。またオーバーライドするのではなく、別の自作メソッドで返り値を定義してViewController で呼び出しても、OperationQueueに入れたタスクとしては実行されず、根源的な解決にはならないので実施しませんでした。 *****何を・どのように調べたのか***** 上記を解決するために、以下のキーワードで検索しました。 * swift Operation タスク UIの変更 参考にした記事のURLは以下です。 【Swift】非同期処理「Operation」について 1,2のエラー、問題点に対して何か解決案があればアドバイスよろしくお願いします。 またOperationを使用したこの実装例であればこの2案と異なっていても構いません。 またそもそも 全てをGCDで実装するのではなくOperation,OperationQueueを使っているのは、最終的な目標として 1. 実行ボタンを押すと3つA,B,CのAPIを順に実行しどれか一つでも失敗したらその処理を終了するという依存関係のある処理を行い、結果を画面に表示すること 2. 別のボタンを処理の途中で押すとキャンセルできるようにしたい、 3. そしてこれらの実行コードがネストにならないようにしたい。 これらを実装したいからです。
回答: あなたの(「試したこと1」で)最も問題があるのは、この行です。 ``` ThirdViewController().returnLabel.text = "オペレーションから値の操作" ``` `ThirdViewController()`というイニシャライザ呼び出しで、**実際に画面表示を担当しているインスタンスとは別の新しいインスタンスを**、**storyboardの設定を無視して** 作成してしまっています。Storyboardを無視したインスタンスの作成ですから、iOSはIBOutletの接続なんてやってくれていないため、当然`returnLabel`はnilのままですし、たとえstoryboard経由でインスタンスを作成したとしても、画面表示に関係ない別インスタンスの`UILabel`を操作しても画面には何も反映されません。 一般に `何かのViewController()`というイニシャライザ呼び出しは意味のないインスタンスを作成するので使っちゃダメ ============================================================ と覚えておいた方が良いでしょう。 あなたが書かれているようなことを実現したいのであれば、**実際に表示を担当しているViewControllerのインスタンスをOperationに渡してやる** 必要があるでしょう。 ``` class ThirdViewController: UIViewController { // Lableの定義、タスク実行後ここに値を入れたい。 @IBOutlet weak var returnLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() // キューの作成 let queue = OperationQueue() queue.name = "com.example.my_operation_queue" queue.maxConcurrentOperationCount = 1 queue.qualityOfService = .userInitiated // 作成したキューにタスクを入れる var operations: [Operation] = [] let first = FirstOperation() first.thirdVC = self //<-実際に表示を担当しているVCを渡す operations.append(first) operations.append(SecendOperation()) operations[1].addDependency(operations[0]) queue.addOperations(operations, waitUntilFinished: false) print("OperationQueueにタスクを追加しました。") } } var flag = true //<- `flag`なんて意味不明の変数名の使用はやめましょう class FirstOperation: Operation { var thirdVC: ThirdViewController? //<-実際に表示を担当しているVCを受け取る override func main() { if flag { print("This is FirstOperation step") print("1つめ\(Thread.isMainThread)") DispatchQueue.main.async { print("2つめ\(Thread.isMainThread)") self.thirdVC?.returnLabel.text = "オペレーションから値の操作" //<-実際に表示を担当しているVCを操作する } } else { print("FirstOperation cancel") } } } ``` ### 「試したこと1を経て、再度試したこと」について Operationで実行される処理から「返り値」を返すことはできません。処理結果から何らかの値を渡したいのであれば、他の方法を考えてください。