【Swift、Objective-c】画面遷移とメモリ使用について



Swift、Objective-cでの画面遷移をする際の遷移方法、メモリ使用についてまとめました。


#画面遷移する方法

ViewController間での画面遷移は、storyboard ID、Segue Identifierを使用する方法と
dismissViewControllerAnimatedを使用する方法があります。

```objective_c:Objective-c

//storyboard IDを使用した画面遷移
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"storyboard ID"];
[self presentViewController:vc animated:NO completion:nil];

//Segue Identifierを使用した画面遷移
[self performSegueWithIdentifier:@"Segue Identifier" sender:self];

//dismissViewControllerAnimatedを使用した画面遷移
[self dismissViewControllerAnimated:NO completion:nil];
```

```Swift:Swift

//storyboard IDを使用した画面遷移
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "storyboard ID") as! nextViewController
        self.present(secondViewController, animated: true, completion: nil)

//Segue Identifierを使用した画面遷移
self.performSegue(withIdentifier: "Segue Identifier", sender: self)

//dismissViewControllerAnimatedを使用した画面遷移
self.dismiss(animated: false, completion: nil)
```


#画面遷移する場合のメモリ使用量
２つのViewController間を画面遷移した場合、メモリ使用量の変化は以下のようになります。

- <b>dismissViewControllerAnimatedで画面遷移をした場合のメモリ使用量</b>
画面遷移した時に、メモリが解放されます。
![dismiss画面遷移.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431502/f99be2fa-769d-ffb4-b42a-e58b2fb2beeb.jpeg)


- <b>storyboard ID、Segue Identifierで画面遷移をした場合のメモリ使用量</b>
画面遷移をした時に新しく画面を作成していくため、画面遷移してもメモリが解放されず、
メモリが溜まっていきます。
![present画面遷移.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431502/6b6770d4-5ceb-989b-b632-4426dc80e81f.jpeg)

dismissViewControllerAnimated以外での画面遷移では新しく画面を作成する。
そのため、storyboard ID、Segue Identifierのみで画面遷移を続けた場合、メモリが解放されず溜まっていき、
結果として動作が重くなりアプリが強制終了してしまう。
そのため、新しい画面への画面遷移以外は、dismissViewControllerAnimatedで戻った方が良い。


#dismissViewControllerAnimatedで遷移した場合の問題点
メモリ解放のため、dismissViewControllerAnimatedを使用した画面遷移を使用していきたいが、dismissViewControllerAnimatedは、現在表示されているViewControllerを削除することで画面遷移するため、戻った後のViewControllerは更新されない。

そのため、TableViewの画面情報を再表示したい場合、追加の処理を行う必要がある。



#NSNotificationを使用したTableViewの更新

解決策として事前にmainViewControllerでNSNotificationの通知要求を登録しておき、遷移後のViewControllerから画面遷移する時に、通知を送ることで画面遷移後にTableViewを更新することができます。

```objective_c:Objective-c　mainViewController
- (void)viewDidLoad {
     [super viewDidLoad];

     //通知要求の登録をする
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hoge:) name:@"reload" object:nil];
}

//通知を受信した時に実行する
-(void)hoge:(NSNotification *)notification {
     if([[notification name]isEqual:@"reload"]) {
          //TableViewの更新処理
          [tableView reloadData];
     }
}
```

```objective_c:Objective-c　nextViewController

//画面遷移後に通知を送信する
[self dismissViewControllerAnimated:NO completion:^{
     [[NSNotificationCenter defaultCenter]postNotificationName:@"reload" object:self];
}];
```



```Swift:Swift　mainViewController

override func viewDidLoad() {
     super.viewDidLoad()

     //通知要求の登録をする
     let nc = NotificationCenter.default
     nc.addObserver(self, selector: #selector(hoge), name: Notification.Name(rawValue:"reload"), object: nil)
}

//通知を受信した時に実行する
@objc func hoge(notification: Notification?) {
     if notification!.name.rawValue == "reload" {
          tableView.reloadData()
     }
}
```

```Swift:Swift　nextViewController
//画面遷移後に通知を送信する
self.dismiss(animated: false, completion: {
     NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reload"), object: nil)
})
```


#mainViewControllerまで一気に戻る場合

複数画面遷移している状態から一気にmainViewControllerまで戻る場合以下のようにすれば良い。

```objective_c:Objective-c

[[UIApplication sharedApplication].windows[0].rootViewController dismissViewControllerAnimated:NO completion:nil];
```

```Swift:Swift

let window = UIApplication.shared.windows[0].rootViewController
window?.dismiss(animated: false, completion: nil)
```

#参考

[presentViewController:animated:completion:](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621380-presentviewcontroller?language=objc)
[dismissViewControllerAnimated:completion:](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismissviewcontrolleranimated)
https://tutorialmore.com/questions-2605800.htm