[Swift]曇りガラスのかかったサイドバー（blur, Xcode6 beta6)


![sideMenu.gif](https://qiita-image-store.s3.amazonaws.com/0/27810/8f71c904-4188-6908-d8aa-b62f87602626.gif "sideMenu.gif")

いい感じのBlurEffectがかかっているサイドバーの作り方です。

## 必要なファイルの作成

以下の2つのファイルを作成します。

```SideMenu.swift
import UIKit

@objc protocol SideMenuDelegate {
    func sideMenuDidSelectItemAtIndex(index:Int)
    optional func sideMenuWillOpen()
    optional func sideMenuWillClose()
}

class SideMenu : NSObject, MenuTableViewControllerDelegate {
    
    let menuWidth : CGFloat = 160.0
    let menuTableViewTopInset : CGFloat = 64.0 // if you use translusent navigation bar
    let sideMenuContainerView =  UIView()
    let sideMenuTableViewController = MenuTableViewController()
    var animator : UIDynamicAnimator!
    let sourceView : UIView!
    var delegate : SideMenuDelegate?
    var isMenuOpen : Bool = false
    
    init(sourceView: UIView, menuData:Array<String>) {
        super.init()
        self.sourceView = sourceView
        self.sideMenuTableViewController.tableData = menuData
        
        self.setupMenuView()
        
        animator = UIDynamicAnimator(referenceView:sourceView)
        // Add show gesture recognizer
        var showGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("handleGesture:"))
        showGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Right
        sourceView.addGestureRecognizer(showGestureRecognizer)
        
        // Add hide gesture recognizer
        var hideGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("handleGesture:"))
        hideGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Left
        sideMenuContainerView.addGestureRecognizer(hideGestureRecognizer)
    }
    
    
    func setupMenuView() {
        
        // Configure side menu container
        sideMenuContainerView.frame = CGRectMake(-menuWidth-1.0, sourceView.frame.origin.y, menuWidth, sourceView.frame.size.height)
        sideMenuContainerView.backgroundColor = UIColor.clearColor()
        sideMenuContainerView.clipsToBounds = false
        sideMenuContainerView.layer.masksToBounds = false;
        sideMenuContainerView.layer.shadowOffset = CGSizeMake(1.0, 1.0);
        sideMenuContainerView.layer.shadowRadius = 1.0;
        sideMenuContainerView.layer.shadowOpacity = 0.125;
        sideMenuContainerView.layer.shadowPath = UIBezierPath(rect: sideMenuContainerView.bounds).CGPath

        sourceView.addSubview(sideMenuContainerView)
        
        // Add blur view
        var visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light)) as UIVisualEffectView
        visualEffectView.frame = sideMenuContainerView.bounds
        sideMenuContainerView.addSubview(visualEffectView)
        
        // Configure side menu table view
        sideMenuTableViewController.delegate = self
        sideMenuTableViewController.tableView.frame = sideMenuContainerView.bounds
        sideMenuTableViewController.tableView.clipsToBounds = false
        sideMenuTableViewController.tableView.separatorStyle = .None
        sideMenuTableViewController.tableView.backgroundColor = UIColor.clearColor()
        sideMenuTableViewController.tableView.scrollsToTop = false
        sideMenuTableViewController.tableView.contentInset = UIEdgeInsetsMake(menuTableViewTopInset, 0, 0, 0)
        
        sideMenuTableViewController.tableView.reloadData()
        
        sideMenuContainerView.addSubview(sideMenuTableViewController.tableView)
    }
    
    func handleGesture(gesture: UISwipeGestureRecognizer) {
        
        if (gesture.direction == .Left) {
            toggleMenu(false)
             delegate?.sideMenuWillClose?()
        }
        else{
            toggleMenu(true)
             delegate?.sideMenuWillOpen?()
        }
    }
    
    func toggleMenu (shouldOpen: Bool) {
        animator.removeAllBehaviors()
        isMenuOpen = shouldOpen
        let gravityDirectionX: CGFloat = (shouldOpen) ? 0.5 : -0.5;
        let pushMagnitude: CGFloat = (shouldOpen) ? 20.0 : -20.0;
        let boundaryPointX: CGFloat = (shouldOpen) ? menuWidth : -menuWidth-1.0;
        
        let gravityBehavior = UIGravityBehavior(items: [sideMenuContainerView])
        gravityBehavior.gravityDirection = CGVectorMake(gravityDirectionX, 0.0)
        animator.addBehavior(gravityBehavior)
        
        let collisionBehavior = UICollisionBehavior(items: [sideMenuContainerView])
        collisionBehavior.addBoundaryWithIdentifier("menuBoundary", fromPoint: CGPointMake(boundaryPointX, 20.0),
            toPoint: CGPointMake(boundaryPointX, sourceView.frame.size.height))
        animator.addBehavior(collisionBehavior)
        
        let pushBehavior = UIPushBehavior(items: [sideMenuContainerView], mode: UIPushBehaviorMode.Instantaneous)
        pushBehavior.magnitude = pushMagnitude
        animator.addBehavior(pushBehavior)
        
        let menuViewBehavior = UIDynamicItemBehavior(items: [sideMenuContainerView])
        menuViewBehavior.elasticity = 0.3
        animator.addBehavior(menuViewBehavior)
    }
    
    func menuControllerDidSelectRow(indexPath:NSIndexPath) {  
         delegate?.sideMenuDidSelectItemAtIndex(indexPath.row)
    }
    
    func toggleMenu () {
        if (isMenuOpen) {
            toggleMenu(false)
        }
        else {
            toggleMenu(true)
        }
    }
}
```

```MenuTableViewController.swift
//
//  MenuController.swift
//  SwiftSideMenu
//
//  Created by Evgeny on 23.07.14.
//  Copyright (c) 2014 Evgeny Nazarov. All rights reserved.
//

import UIKit

protocol MenuTableViewControllerDelegate {
    func menuControllerDidSelectRow(indexPath:NSIndexPath)
}

class MenuTableViewController: UITableViewController {

    var delegate : MenuTableViewControllerDelegate?
    var tableData : Array<String> = []
    
    override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
        return 1
    }
    
    override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return tableData.count
    }
    
    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        
        var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell
        
        if (cell == nil) {
            cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CELL")
            cell!.backgroundColor = UIColor.clearColor()
            cell!.textLabel.textColor = UIColor.darkGrayColor()
            let selectedBackgroundView = UIView(frame: CGRectMake(0, 0, cell!.frame.size.width, cell!.frame.size.height))
            selectedBackgroundView.backgroundColor = UIColor.grayColor().colorWithAlphaComponent(0.2)
            cell!.selectedBackgroundView = selectedBackgroundView
        }
        
        cell!.textLabel.text = tableData[indexPath.row]
        
        return cell
    }
    
    override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
        return 50.0
    }
    
    override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
        delegate?.menuControllerDidSelectRow(indexPath)
    }
}
```

## VCにDelegateを設定

```VC.swift
class ViewController: UIViewController, SideMenuDelegate {
	.
	.	
	.
    var sideMenu : SideMenu?
	
	override func viewDidLoad() {
        super.viewDidLoad()
    
        sideMenu = SideMenu(sourceView: self.view, menuData: ["UIDynamics", "UIGestures", "UIBlurEffect"])
        sideMenu!.delegate = self
        
        
    }

    func sideMenuDidSelectItemAtIndex(index: Int) {
        sideMenu?.toggleMenu()
    }
    
    @IBAction func toggleSideMenu(sender: AnyObject) {
        sideMenu?.toggleMenu()
    }


```

## Navigation Controllerの作成

Navigation Controllerを作成して、Bar button itemを作成します。
作成したBar button Itemと上記の@IBActionを紐付ければ完了です。
![スクリーンショット 2014-08-26 13.19.19.png](https://qiita-image-store.s3.amazonaws.com/0/27810/cf49142f-fc5c-1883-c07b-fd7ecab6db09.png "スクリーンショット 2014-08-26 13.19.19.png")

![スクリーンショット 2014-08-26 13.19.43.png](https://qiita-image-store.s3.amazonaws.com/0/27810/acccb267-8086-0f7b-5fc9-a26bd5ebf8b4.png "スクリーンショット 2014-08-26 13.19.43.png")　　　　![スクリーンショット 2014-08-26 13.20.32.png](https://qiita-image-store.s3.amazonaws.com/0/27810/2ce11785-15ca-85b9-1534-5f802d304cd8.png "スクリーンショット 2014-08-26 13.20.32.png")

## 参考
下記を参考にして、beta6用に書き換えました。
https://github.com/evnaz/ENSwiftSideMenu

## その他の記事
- [SwiftでFacebook SDKを使用したログイン機能（Xcode6 beta6）](http://qiita.com/kiiita/items/9b22bc680856353733de)
- [SwiftのNotificationでHello, Worldして、アクションを3つ作ってみた](http://qiita.com/kiiita/items/453426e3873e58dc8768)

---

★女性エンジニア向けのイベントやります
<a class="doorkeeper-registration-widget" href="http://zigexn.doorkeeper.jp/events/14687">9/17(水)開催 - ZIGExN Swift Girls 〜集え☆iPhoneアプリを作りたい女子〜</a><script src="http://widgets.doorkeeper.jp/w/widget.js"></script>