obj-cからswiftへ書き換え：Container View Controller

#はじめに
swiftとContainer View Controllerの実装の把握のために
Facebook風な画面のアニメーションを行うアプリのソース(obj-c)をswiftに書き換えてみました。

Container ViewはiOS6から使えるようになった機能、swiftはiOS7以上、ということで対象はiOS7以上のアプリ制作です

>ご指摘から内容を
`NavigationItem` → `BarButtonItem`と変更しています。

#概要

* ViewContoller に Container View Controllerを複数個乗せる
* ButtonからのEventをNSNotificationCenterで受ける
* 画面を左右にアニメーションさせる
* がんばってconstrainsつけてみる

#手順

 * storyboardへの配置
 * クラスの実装

#storyboardでContainerViewを配置

ViewControlleにContainer Viewを配置すると
segueでenmedされているViewController が追加されます。

Document Outlineに複数のContainerがあると紛らわしいので
lableにコントローラー名を入れておきます。

![スクリーンショット 2014-10-05 8.22.13.png](https://qiita-image-store.s3.amazonaws.com/0/12362/9f80a8b5-e250-67a3-df9d-de43512c288d.png)

先に作成しているViewControllerをembedする場合はContainerから対象へsegueを引くと選択できます

![スクリーンショット 2014-10-05 8.40.37.png](https://qiita-image-store.s3.amazonaws.com/0/12362/5fdb85da-f29b-111d-1105-bf05c8d07ab7.png)

(1) Container Viewを３つ乗せたViewControllerを配置
(2) 空のViewControllerのクラスファイルを4つ作ります

 * ContainerVC.swift
 * MenuVC.swift
 * MainVC.swift
 * ProfileVC.swift

(3) storyboardに配置したViewContollerに(2)で作成したクラスファイルを指定します
(4) ContainerVC以外のViewContollerに背景色をつけます
(5) MainVCに

* NavigationBar
* ~~NavigationItem~~ BarButtonItem（二つ）

を配置します。

![スクリーンショット 2014-10-05 9.42.46.png](https://qiita-image-store.s3.amazonaws.com/0/12362/fd3a3e4f-a10a-7050-061e-217677caacc9.png)

#クラスファイルでの実装

##設定を共有するクラス

元のコード

```objc
#import <Foundation/Foundation.h>
@interface ShareSettings : NSObject
@property (nonatomic) BOOL menuTapped;
@property (nonatomic) BOOL profileTapped;
+ (id)sharedSettings;
@end
```

> +(id)sharedSettings;

ここが困りました。

杉上さんが寄稿されている記事から参考にさせていただいて
http://qiita.com/susieyy/items/f71435cc962e70d81b37#2-21
書き換えたものが次の通りです。

```swift:ShareSettings.swift
import UIKit

class ShareSettings: NSObject {
    
    var menuTapped: Bool!
    var profileTapped: Bool!
    
    override init() {
        super.init()
    }
    override var description: String { return "ShareSetting class" }
    
    class var sharedInstance : ShareSettings {
        struct Static {
            static let instance : ShareSettings = ShareSettings()
        }
        return Static.instance
    }
}
```


##ContainerVC

（1）3つのContainer View へのOutletと設定の初期化を記述します
outletの記述後、@IBOutletで指定したContainerViewにstoryboardで接続します

```swift:ContainerVC.swift
class ContainerVC: UIViewController {
    @IBOutlet weak var menuVC: UIView!
    @IBOutlet weak var profileVC: UIView!
    @IBOutlet weak var mainVC: UIView!
    var shareSettings :ShareSetting = ShareSetting.sharedInstance;
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        shareSettings.menuTapped = false
        shareSettings.profileTapped = false
    }
//略
}
```

（2）NSNotificationCenterの追加と削除

```swift
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        NSNotificationCenter.defaultCenter().addObserver(
            self, selector: "menuTapped", name: "menuTappedNotification", object: nil)
        NSNotificationCenter.defaultCenter().addObserver(
            self, selector: "profileTapped", name: "profileTappedNotification", object: nil)
    }
    
    override func viewDidDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(
            self, name: "menuTappedNotification", object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(
            self, name: "profileTappedNotification", object: nil)
    }
```

（3）~~NavigationItem~~　BarButtonItemを押した時の動作をつける

* 左のメニュー画面コンテナ、右のプロフィール画面コンテナの横幅は固定
* 中央のメイン画面コンテナはフルサイズ
* 中央のメイン画面は左、右コンテナより大きい

とルールを決めて
constrainsをつけます。

```swift

    func menuTapped(){
        if (shareSettings.menuTapped.boolValue){
            UIView.animateWithDuration(
                0.3,
                animations: {
                    self.mainVC.frame =
                        CGRectMake(0, self.mainVC.frame.origin.y, self.mainVC.frame.size.width, self.mainVC.frame.size.height)
                    //hidden
                    self.menuVC.frame =
                        CGRectMake( -self.menuVC.frame.size.width, self.menuVC.frame.origin.y, self.menuVC.frame.size.width, self.menuVC.frame.size.height)
                }
            )
        } else {
            UIView.animateWithDuration(
                0.3,
                animations: {
                    self.mainVC.frame =
                        CGRectMake(self.menuVC.frame.size.width, self.mainVC.frame.origin.y, self.mainVC.frame.size.width, self.mainVC.frame.size.height)
                    //appear
                    self.menuVC.frame =
                        CGRectMake( 0, self.menuVC.frame.origin.y, self.menuVC.frame.size.width, self.menuVC.frame.size.height)
                }
            )
        }
        shareSettings.menuTapped = !shareSettings.menuTapped
    }
    
    func profileTapped(){
        if (shareSettings.profileTapped.boolValue){
            UIView.animateWithDuration(
                0.3,
                animations: {
                    self.mainVC.frame =
                        CGRectMake(0, self.mainVC.frame.origin.y, self.mainVC.frame.size.width, self.mainVC.frame.size.height)
                    //hidden
                    self.profileVC.frame =
                        CGRectMake(self.view.frame.size.width, self.profileVC.frame.origin.y, self.profileVC.frame.size.width, self.profileVC.frame.size.height)
                }
            )
        } else {
            UIView.animateWithDuration(
                0.3,
                animations: {
                    self.mainVC.frame =
                        CGRectMake(-self.profileVC.frame.size.width, self.mainVC.frame.origin.y, self.mainVC.frame.size.width, self.mainVC.frame.size.height)
                    //appear
                    self.profileVC.frame =
                        CGRectMake(self.view.frame.size.width - self.profileVC.frame.size.width, self.profileVC.frame.origin.y, self.profileVC.frame.size.width, self.profileVC.frame.size.height)
                }
            )
        }
        shareSettings.profileTapped = !shareSettings.profileTapped
    }
```
起動時
![スクリーンショット 2014-10-07 16.55.45.png](https://qiita-image-store.s3.amazonaws.com/0/12362/8c29216e-69f5-cfc6-b86a-1b9063744ae0.png)

左ボタン（Menu）を押したとき
![スクリーンショット 2014-10-07 16.56.34.png](https://qiita-image-store.s3.amazonaws.com/0/12362/71e9605a-d339-0cea-1dc2-85ed767b4153.png)

右ボタン（Profile）を押したとき
![スクリーンショット 2014-10-07 16.57.28.png](https://qiita-image-store.s3.amazonaws.com/0/12362/11f66df5-2cee-e12d-e063-8a5cbc6460c0.png)



##MainVC
NotificationCenterへ通知する部分を記述します。
@IBActionで指定した ~~NavigationItem~~ BarButtonItemにstoryboard上で接続します

```swift:MainVC.swift
import UIKit

class MainVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func menuTapped(sender: AnyObject) {
        NSNotificationCenter.defaultCenter().postNotificationName("menuTappedNotification", object: nil)
    }
    
    @IBAction func profileTapped(sender: AnyObject) {
        NSNotificationCenter.defaultCenter().postNotificationName("profileTappedNotification", object: nil)
    }
}

```

#constrainsをつける

参考程度にしておいてください
##MainVC
![スクリーンショット 2014-10-07 17.47.37.png](https://qiita-image-store.s3.amazonaws.com/0/12362/b3cb0971-ea58-a105-4eda-8d81dd7081e6.png)


##MenuVC
constrains
![スクリーンショット 2014-10-07 17.48.23.png](https://qiita-image-store.s3.amazonaws.com/0/12362/6090401c-999c-1cb9-4d1e-366460243b3e.png)

##ProfileVC

constrains
![スクリーンショット 2014-10-07 17.45.17.png](https://qiita-image-store.s3.amazonaws.com/0/12362/93e47e4a-70ee-215f-0425-f16f1f731ade.png)


#Add Class Size Customization

※ここではざっと触れるだけに
デフォルトでは設定したサイズ別に有効になっていますので、全般的に設定を有効にする方がらくちんです。

![スクリーンショット 2014-10-07 17.58.33.png](https://qiita-image-store.s3.amazonaws.com/0/12362/843a81ec-2714-36bd-e4f9-a307b4df740c.png)



#参考URL

How to Use Container View Controller
http://mobileoop.com/how-to-use-container-view-controller

Swiftコーディング規約@Wantedly
http://qiita.com/susieyy/items/f71435cc962e70d81b37
#さいごに
ControllerView外からクラスを参照するのが手間で、Qiitaの記事に助けられた感じです。
コード補完で補えるところと、swiftの仕様に置き換えなければいけないところが分かりました。

オリジナルのコードは、iPhoneのサイズがイロイロ変わることを想定していないものだったので、アニメーションのコードとconstrainsの設定を追記しています。
ただ、全画面対応を狙って苦戦している状態ですので、constrainsの設定については後ほど別記事で・・・