WebViewをスクロールするとUIToolbarを表示させる

WebViewを下の方にスクロールすると画面の下からUIToolbarを表示させる。

Code

import UIKit

class ViewController: UIViewController,UIWebViewDelegate,UIGestureRecognizerDelegate,UIScrollViewDelegate {
    var webView:UIWebView!

    let urlStr:String = "https://www.youtube.com"

    var toolbarFrame:CGRect!


    let radiusOfIndiCator:CGFloat = 44
    let offsetYOfToolBar:CGFloat = 44
    let durationOfToolBar:Double = 0.4
    let boundaryOfY = 200

    override func viewDidLayoutSubviews() {
        if self.toolbarFrame == nil {
            self.toolbarFrame = self.navigationController!.toolbar.frame
            self.toolbarFrame.origin.y = self.view.frame.size.height + offsetYOfToolBar

        }
        
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        // Add WebView
        self.webView = UIWebView(frame: CGRectMake(0,0, self.view.frame.size.width,self.view.frame.size.height))
        let req:NSURLRequest = NSURLRequest(URL: NSURL(string: self.urlStr)!)
        self.webView.delegate  = self

        self.webView.loadRequest(req)
        self.view.addSubview(webView)
        self.navigationController?.toolbar.hidden = true


    }


    func scrollViewDidScroll(scrollView: UIScrollView) {

        let scrollY = scrollView.layer.presentationLayer().bounds.origin.y
            if Int(scrollY) < self.boundaryOfY  {
                // hide toolbar
                let nextY = self.toolbarFrame.origin.y + self.offsetYOfToolBar

                UIView.animateWithDuration(self.durationOfToolBar) {
                    self.navigationController?.toolbar.frame.origin.y = nextY
                    return
                }



            }else{
                // show toolbar
                self.navigationController?.toolbar.hidden = false

                let nextY = self.toolbarFrame.origin.y - self.offsetYOfToolBar

                UIView.animateWithDuration(self.durationOfToolBar) {
                    self.navigationController?.toolbar.frame.origin.y = nextY
                    
                    return
                }
                
                



        }

    }
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
    }
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.toolbar.barTintColor = UIColor.whiteColor()
        
    }

    func setTabBarVisible(visible:Bool, animated:Bool) {

        //* This cannot be called before viewDidLayoutSubviews(), because the frame is not set before this time

        // bail if the current state matches the desired state
        if (tabBarIsVisible() == visible) { return }
        // get a frame calculation ready
        let frame = self.tabBarController?.tabBar.frame
        let height = frame?.size.height
        let offsetY = (visible ? -height! : height)


        let duration:NSTimeInterval = (animated ? 0.3 : 0.0)

        //  animate the tabBar
        if frame != nil {
            UIView.animateWithDuration(duration) {
                self.tabBarController?.tabBar.frame = CGRectOffset(frame!, 0, offsetY!)
                return
            }
        }
    }

    func webViewDidFinishLoad(webView: UIWebView) {
        self.webView.scrollView.delegate = self

    }

    func tabBarIsVisible() ->Bool {
        return self.tabBarController?.tabBar.frame.origin.y < CGRectGetMaxY(self.view.frame)
    }

 


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

サンプルプロジェクトはこちらからダウンロードできます。

複数のGestureがコンフリクトする問題を解決する

UITableViewCellのSwipeで表示されるGesutreとUIViewControllerで登録したGestureがコンフリクトしてUITableViewCellのGesutureが動作しなくなってハマっていたけど、以下のメソッドを呼ぶことで解決した。

  func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

ButtonをタップするとPickerViewを表示させる

PickerViewを画面にそのまま表示させると、スクロールするときのユーザビリティが著しく低下するのでボタンをタップしたらPickerViewを出すAlertPickerViewを作った。


import Foundation
import UIKit


class AlertPickerView: UIView {
    var pickerView: UIPickerView!
    var pickerToolbar: UIToolbar!
    var toolbarItems: [UIBarItem]!
    var items:Array<String>!
    let heightOfPickerView:CGFloat = 216
    let heightOfToolbar:CGFloat = 44
    var backgroundColorOfPickerView  = UIColor.whiteColor()
    var backgroundColorOfToolbar = UIColor.whiteColor()
    var textColorOfToolbar = UIColor.blackColor()

    var delegate: AlertPickerViewDelegate? {
        didSet {
            pickerView.delegate = delegate
        }
    }
    private var selectedRows: [Int]?


    override init(frame: CGRect) {
        super.init(frame: frame)
        initFunc()
    }
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initFunc()
        println("initfunc")
    }

    private func initFunc() {
        let screenSize = UIScreen.mainScreen().bounds.size
        self.backgroundColor = UIColor.blackColor()

        pickerToolbar = UIToolbar()
        pickerView = UIPickerView()
        toolbarItems = []

        pickerToolbar.translucent = false
        pickerView.showsSelectionIndicator = true
        pickerView.backgroundColor = self.backgroundColorOfPickerView


        self.frame = CGRectMake(0, screenSize.height, screenSize.width, self.heightOfPickerView + self.heightOfToolbar)

        //pickerToolbar
        pickerToolbar.frame = CGRectMake(0, 0, screenSize.width, self.heightOfToolbar)
        pickerToolbar.barTintColor = self.backgroundColorOfPickerView

        //pickerView
        pickerView.frame = CGRectMake(0,self.heightOfToolbar, screenSize.width, self.heightOfPickerView)
        pickerView.backgroundColor = self.backgroundColorOfPickerView


        let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
        space.width = 12

        let cancelItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: "cancelPicker")
        let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)

        let doneButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: Selector("endPicker"))

        toolbarItems! += [space, cancelItem, flexSpaceItem, doneButtonItem, space]
        pickerToolbar.setItems(toolbarItems, animated: false)
        pickerToolbar.tintColor = self.textColorOfToolbar
        pickerToolbar.barTintColor = self.backgroundColorOfToolbar


        self.addSubview(pickerToolbar)
        self.addSubview(pickerView)
    }
    func showPicker() {
        if selectedRows == nil {
            selectedRows = getSelectedRows()
        }
        delegate?.pickerViewWillShow?(pickerView)
        let screenSize = UIScreen.mainScreen().bounds.size

        UIView.animateWithDuration(0.2 ,animations: { () -> Void in

            self.frame = CGRectMake(0, screenSize.height - (self.heightOfToolbar + self.heightOfPickerView), screenSize.width, self.heightOfPickerView + self.heightOfToolbar)

            }) { (completed:Bool) -> Void in
        delegate?.pickerViewDidSHow?(pickerView)
        }
    }



    func cancelPicker() {
        hidePicker()
        restoreSelectedRows()
        selectedRows = nil
    }
    func endPicker() {
        hidePicker()
        delegate?.pickerView?(pickerView, didSelect: getSelectedRows())
        selectedRows = nil
    }
    private func hidePicker() {
        let screenSize = UIScreen.mainScreen().bounds.size
        delegate?.pickerViewWillHide?(pickerView)
        UIView.animateWithDuration(0.2 ,animations: { () -> Void in

             self.frame = CGRectMake(0, screenSize.height, screenSize.width, self.heightOfToolbar + self.heightOfPickerView)

            }) { (completed:Bool) -> Void in
        delegate?.pickerViewDidHide?(pickerView)
        }
    }
    private func getSelectedRows() -> [Int] {
        var selectedRows = [Int]()
        for i in 0 ... pickerView.numberOfComponents - 1 {
            selectedRows.append(pickerView.selectedRowInComponent(i))
        }
        return selectedRows
    }
    private func restoreSelectedRows() {
        for i in 0..<selectedRows!.count {
            pickerView.selectRow(selectedRows![i], inComponent: i, animated: true)
        }
    }
}

@objc
protocol AlertPickerViewDelegate: UIPickerViewDelegate {
    optional func pickerView(pickerView: UIPickerView, didSelect numbers: [Int])
    optional func pickerViewDidSHow(pickerView: UIPickerView)
    optional func pickerViewDidHide(pickerView: UIPickerView)
    optional func pickerViewWillHide(pickerView: UIPickerView)
    optional func pickerViewWillShow(pickerView: UIPickerView)
    optional func pickerViewDidShow(pickerView: UIPickerView)

}







使い方

import UIKit

class ViewController: UIViewController,AlertPickerViewDelegate,UIPickerViewDelegate {
    var pickerView: AlertPickerView!
    let array = ["foo","bar","baz"]


    override func viewDidLoad() {
        super.viewDidLoad()
        self.pickerView = AlertPickerView()

        self.pickerView.items = array
        self.pickerView.delegate = self
        self.view.addSubview(pickerView)


        var button = UIButton(frame: CGRectMake(100,100, 200, 44))
        button.setTitle("Show Picker", forState: UIControlState.Normal)

        button.addTarget(self, action: "showPicker", forControlEvents: UIControlEvents.TouchDown)
        button.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(button)



    }


    func showPicker() {
        self.pickerView.showPicker()
    }
    // for delegate
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.pickerView.items.count
    }
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        return self.pickerView.items[row]
    }
    func pickerView(pickerView: UIPickerView, didSelect numbers: [Int]) {
        println("selected \(numbers)")
    }

    func pickerViewDidHide(pickerView: UIPickerView) {
        println("hided pickerview")
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

このコードを実行すると下の画面になる。

iOS Simulator Screen Shot 2015.08.11 16.31.09

コードはGithubからダウンロードできます。

[Swift] 文字列からNSDateオブジェクトを作成

よく利用するのでメモしておく。

Code

  
    func parse(dateStr:String) -> NSDate {
        var dateFmt = NSDateFormatter()
        dateFmt.timeZone = NSTimeZone.defaultTimeZone()
        dateFmt.dateFormat = "yyyy-MM-dd"
        return dateFmt.dateFromString(dateStr)!
    }

使い方

 parse("2014-07-20")

無料iOSアプリ『睡眠チェック!』をリリースしました。

わずか8個の4択問題に答えるだけであなたの睡眠の質をチェックできる、『睡眠チェック!』をリリースしました。

特徴

信頼性の高い診断方式を元に作成

設問・診断基準については、世界保健機関(WHO)が中心になって設立した「睡眠と健康に関する世界プロジェクト」が作成した世界共通の不眠症判定法であるアテネ不眠尺度を採用しています。

睡眠に関する読み物を掲載

睡眠のことに詳しく慣れる読み物を厳選して掲載しています。

睡眠の質をグラフで表示

グラフ化することで客観的に自分の睡眠の質を測ることができます。

終わりに

アプリの説明は以上になります。
個人的にこのアプリを作るにあたってプログラムの部分は以前作った『うつチェック!』を基に作成したから苦労せずに作れたけど、睡眠について調べる作業に苦労したけど、そのおかげでよく眠れるようになったのでよかったです。w

良かったら『睡眠チェック!』をダウンロードしてみてください。