swift

【swift2.2】初心者がswiftで作ったカレンダーアプリ ⑤プログラムを書く

カレンダーを表示するシンプルなアプリを作ります。

目次
①プロジェクトを作成
②Storyboardにパーツを配置、AutoLayoutを設定
③IBOutlet、IBAction、その他の設定〜前編〜
④IBOutlet、IBAction、その他の設定〜後編〜
⑤プログラムを書く
⑥確認する



プログラムを書く
AppDelegate.swiftを開く、書いてあったプログラムを削除し以下のコードを貼り付ける

AppDelegateDel

AppDelegateWri


AppDelegate.swift

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }
    
    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }
    
    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        NSNotificationCenter.defaultCenter().postNotificationName("applicationDidEnterBackground", object: nil)  
    }
    
    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
        NSNotificationCenter.defaultCenter().postNotificationName("applicationWillEnterForeground", object: nil)
    }
    
    func applicationDidBecomeActive(application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }  
}


ViewController.swiftを開く、書いてあったプログラムを削除し以下のコードを貼り付ける

ViewControllerDel

ViewControllerWri


ViewController.swift
import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
    
    let dateManager = DateManager()
    let cellMargin: CGFloat = 0.3
    var selectedDate = NSDate()
    var today = NSDate()
    let weekArray = ["日", "月", "火", "水", "木", "金", "土"]
    let yearMonthLabelHeight: CGFloat = 60
    
    //ヘッダー
    @IBOutlet weak var header: UIView!
    //前月ボタン
    @IBOutlet weak var prevBtn: UIButton!
    //次月ボタン
    @IBOutlet weak var nextBtn: UIButton!
    //YYYY年M月
    @IBOutlet weak var yearMonthLabel: UILabel!
    //カレンダー
    @IBOutlet weak var calenderCollectionView: UICollectionView!
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        
        calenderCollectionView.delegate = self
        calenderCollectionView.dataSource = self
        
        //カレンダー背景色
        calenderCollectionView.backgroundColor = UIColor.lightGray()
        //ヘッダー背景色
        header.backgroundColor = UIColor.lightGreen()
        //YYYY年M月表示
        yearMonthLabel.text = dateManager.yearMonthLabel(today)
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    //セルが表示されるときに呼ばれる 1個のセルを描画する毎に呼び出される
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CustomCell
        
        //セル背景色
        cell.backgroundColor = UIColor.whiteColor()
        
        //文字色 土曜日を青・日曜日を赤・それ以外はグレー
        if (indexPath.row % 7 == 0) {
            
            cell.dayLabel.textColor = UIColor.lightRed()
            
        } else if (indexPath.row % 7 == 6) {
            
            cell.dayLabel.textColor = UIColor.lightBlue()
            
        } else {
            
            cell.dayLabel.textColor = UIColor.blackColor()
        }
        
        //曜日・日付文字
        if (indexPath.section == 0) {
            cell.dayLabel.text = weekArray[indexPath.row]
            
            //曜日をタップしたときの背景色(セルと同じ色)
            cell.selectedBackgroundView = dateManager.cellSelectedBackgroundView(UIColor.whiteColor())
            
            //曜日枠線
            dateManager.border(cell, borderWidth: 1.0, borderColor: UIColor.whiteColor().CGColor)
            
        } else {
            cell.dayLabel.text = dateManager.conversionDateFormat(indexPath)
            
            //indexPathをyyyy-MM-ddへ変換
            let yyyyMMddIndexPath = dateManager.nsIndexPathformatYYYYMMDD(indexPath)
            
            //今日の年月日をyyyy-MM-ddへ変換
            let yyyyMMddToday = dateManager.formatYYYYMMDD(today)
            
            //表示月をMMへ変換
            let mmSelectedDate = dateManager.formatMM(selectedDate)
            
            //indexPathをMMへ変換
            let mmIndexPath = dateManager.nsIndexPathformatMM(indexPath)
            
            
            if (yyyyMMddIndexPath == yyyyMMddToday) {
                
                //今日の枠線
                dateManager.border(cell, borderWidth: 2.0, borderColor: UIColor.greenColor().CGColor)
                
            } else {
                
                //今日以外の枠線
                dateManager.border(cell, borderWidth: 1.0, borderColor: UIColor.whiteColor().CGColor)
            }
            
            //前月・次月日付背景色を設定
            if (((mmSelectedDate - 1) == mmIndexPath) ||
                ((mmSelectedDate + 1) == mmIndexPath) ||
                (mmSelectedDate == 12 && mmIndexPath == 1) ||
                (mmSelectedDate == 1 && mmIndexPath == 12)) {
                

                if (yyyyMMddIndexPath == yyyyMMddToday) {
                    
                    //枠線をクリア
                    dateManager.border(cell, borderWidth: 1.0, borderColor: UIColor.whiteColor().CGColor)
                }
                
                cell.backgroundColor = UIColor.WhiteGray()
            }
            
            //日付をタップしたときの背景色
            cell.selectedBackgroundView = dateManager.cellSelectedBackgroundView(UIColor.lightGrayColor())
            
        }
        
        return cell
    }
    
    //セクション0:曜日 セクション1:日付
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 2
    }
    
    // 表示するセルの数
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        if section == 0 {
            // 曜日表示は7つ
            return 7
        } else {
            // 日付表示は月によって変わる
            dateManager.daysAcquisition()
            dateManager.dateForCellAtIndexPath()
            return dateManager.numberOfItems
        }
    }
    
    //1つのセルサイズ
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

        let width: CGFloat = floor(collectionView.frame.size.width / 7)
        let widthRest = collectionView.frame.size.width - (width * 7)
        var height: CGFloat!
        let section0Height: CGFloat = width * 0.5
        
        if indexPath.section == 0 {
            
            height = section0Height
            
        } else {
            
            //縦幅計算で出た余白を今月の最終行にプラスする
            if (CGFloat(indexPath.row / 7 + 1) == dateManager.dayOfMonthLineNumber()) {
                
                height = dateManager.oneHeightSizePlus(collectionView.frame.size.height, section0Height: section0Height)
            }
            
            height = dateManager.oneHeightSize(collectionView.frame.size.height, section0Height: section0Height)
            
        }
        
        //横幅設定
        //土曜日の筋に余った横幅を足す
        if (indexPath.row == 6) || (indexPath.row == 12) ||
            (indexPath.row == 18) || (indexPath.row == 24) ||
            (indexPath.row == 30) || (indexPath.row == 36) {
            
            return CGSizeMake(width + widthRest, height)
            
        } else {
            
            return CGSizeMake(width, height)
        }
    }
    
    //セルの左右マージン
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
        return 0
    }
    
    //セルの上下マージン
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
        return 1
    }
    
    //セクションのマージン
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
        if section == 0 {
            return UIEdgeInsetsMake(0.0, 0.0, 1.0, 0.0);
        } else {
            return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
        }
    }
    
    //前月タップ
    @IBAction func tappedPrevBtn(sender: AnyObject) {
        selectedDate = dateManager.prevMonth(selectedDate)
        calenderCollectionView.reloadData()
        yearMonthLabel.text = dateManager.yearMonthLabel(selectedDate)
    }
    
    //次月タップ
    @IBAction func tappedNextBtn(sender: AnyObject) {
        selectedDate = dateManager.nextMonth(selectedDate)
        calenderCollectionView.reloadData()
        yearMonthLabel.text = dateManager.yearMonthLabel(selectedDate)
    }
    
    //バックグラウンドになったとき
    func enterBackground(notification: NSNotification){
        selectedDate = dateManager.thisMonth(today)
        calenderCollectionView.reloadData()
        yearMonthLabel.text = dateManager.yearMonthLabel(selectedDate)
    }
    
    //フォアグラウンドになったとき
    func enterForeground(notification: NSNotification){
        
    }
    
    //画面が表示される直前に実行される
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.enterBackground(_:)), name:"applicationDidEnterBackground", object: nil)
        
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.enterForeground(_:)), name:"applicationWillEnterForeground", object: nil)
    }
    
    //別の画面に遷移する直前に実行される
    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        
        NSNotificationCenter.defaultCenter().removeObserver(self, name: "applicationDidEnterBackground", object: nil)
        
        NSNotificationCenter.defaultCenter().removeObserver(self, name: "applicationWillEnterForeground", object: nil)
    }
    
}


DateManager.swiftを開く、書いてあったプログラムを削除し以下のコードを貼り付ける

DateManagerDel

DateManagerWri

DateManager.swift
import UIKit

extension NSDate {
    func monthAgoDate() -> NSDate {
        let addValue = -1
        let calendar = NSCalendar.currentCalendar()
        let dateComponents = NSDateComponents()
        dateComponents.month = addValue
        return calendar.dateByAddingComponents(dateComponents, toDate: self, options: NSCalendarOptions(rawValue: 0))!
    }
    
    func monthLaterDate() -> NSDate {
        let addValue: Int = 1
        let calendar = NSCalendar.currentCalendar()
        let dateComponents = NSDateComponents()
        dateComponents.month = addValue
        return calendar.dateByAddingComponents(dateComponents, toDate: self, options: NSCalendarOptions(rawValue: 0))!
    }
    
}

class DateManager: UIViewController {
    
    var currentMonthOfDates: [AnyObject] = []
    var selectedDate = NSDate()
    let daysPerWeek = 7
    var numberOfItems: Int!
    
    //1ヶ月の日数
    func daysAcquisition() -> Int {
        let rangeOfWeeks = NSCalendar.currentCalendar().rangeOfUnit(NSCalendarUnit.WeekOfMonth, inUnit: NSCalendarUnit.Month, forDate: firstDateOfMonth())

        //1ヶ月の週の数
        let numberOfWeeks = rangeOfWeeks.length
        
        //週の数×列の数
        numberOfItems = numberOfWeeks * daysPerWeek
        
        return numberOfItems
    }
    
    //月の初日
    func firstDateOfMonth() -> NSDate {
        let components = NSCalendar.currentCalendar().components([.Year, .Month, .Day],fromDate: selectedDate)

        components.day = 1

        let firstDateMonth = NSCalendar.currentCalendar().dateFromComponents(components)!
        
        return firstDateMonth
    }
    
    func dateForCellAtIndexPath() {
        //月の初日が週の何日目かを計算する
        let ordinalityOfFirstDay = NSCalendar.currentCalendar().ordinalityOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.WeekOfMonth, forDate: firstDateOfMonth())
        
        for(var i = 0; i < numberOfItems; i++) {
            
            //月の初日とindexPath.item番目のセルに表示する日の差
            let dateComponents = NSDateComponents()
            
            dateComponents.day = i - (ordinalityOfFirstDay - 1)

            //表示する月の初日から上記で計算した差を引いた日付を取得
            let date = NSCalendar.currentCalendar().dateByAddingComponents(dateComponents, toDate: firstDateOfMonth(), options: NSCalendarOptions(rawValue: 0))!

            currentMonthOfDates.append(date)
        }
    }
    
    //日付表示
    func conversionDateFormat(indexPath: NSIndexPath) -> String {
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "d"
        return formatter.stringFromDate(currentMonthOfDates[indexPath.row] as! NSDate)
    }
    
    //今日の枠線表示の比較用年月日
    func nsIndexPathformatYYYYMMDD(indexPath: NSIndexPath) -> String {
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter.stringFromDate(currentMonthOfDates[indexPath.row] as! NSDate)
    }
    
    //今月以外の日付背景をグレーにするための比較用月
    func nsIndexPathformatMM(indexPath: NSIndexPath) -> Int {
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "MM"
        return Int(formatter.stringFromDate(currentMonthOfDates[indexPath.row] as! NSDate))!
    }
    
    //前月の表示
    func prevMonth(date: NSDate) -> NSDate {
        currentMonthOfDates = []
        selectedDate = date.monthAgoDate()
        return selectedDate
    }
    
    //次月の表示
    func nextMonth(date: NSDate) -> NSDate {
        currentMonthOfDates = []
        selectedDate = date.monthLaterDate()
        return selectedDate
    }
    
    //今月の表示
    func thisMonth(date: NSDate) -> NSDate {
        currentMonthOfDates = []
        selectedDate = date
        return selectedDate
    }
    
    //YYYY年M月
    func yearMonthLabel(date: NSDate) -> String {
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "yyyy年M月"
        let selectMonth = formatter.stringFromDate(date)
        return selectMonth
    }
    
    //yyyyMMdd変換
    func formatYYYYMMDD(date: NSDate) -> String {
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        let yyyyMMdd = formatter.stringFromDate(date)
        return yyyyMMdd
    }
    
    //MM変換
    func formatMM(date: NSDate) -> Int {
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "MM"
        let mm = formatter.stringFromDate(date)
        return Int(mm)!
    }
    
    //枠線
    func border(cell: AnyObject, borderWidth: CGFloat, borderColor: CGColor){
        cell.layer.borderWidth = borderWidth
        cell.layer.borderColor = borderColor
    }
    
    //セル背景色
    func cellSelectedBackgroundView(color: UIColor) -> UIView {
        let cellSelectedBackgroundView = UIView()
        cellSelectedBackgroundView.backgroundColor = color
        return cellSelectedBackgroundView
    }
    
    //月の行数
    func dayOfMonthLineNumber() -> CGFloat {
        let dayNumber = CGFloat(daysAcquisition())
        let dayOfMonthLineNumber = dayNumber / 7
        return dayOfMonthLineNumber
    }
    
    //カレンダー縦サイズ
    func carenderSize(collectionViewHeight: CGFloat, section0Height: CGFloat) -> CGFloat{
        let carenderSize = floor(collectionViewHeight - section0Height)
        return carenderSize
    }
    
    //セル縦幅
    func oneHeightSize(collectionViewHeight: CGFloat, section0Height: CGFloat) -> CGFloat {
        let oneHeightSize = floor(carenderSize(collectionViewHeight,section0Height: section0Height) / dayOfMonthLineNumber())
        return oneHeightSize
    }
    
    //セル縦幅の余白をプラス
    func oneHeightSizePlus(collectionViewHeight: CGFloat, section0Height: CGFloat) -> CGFloat {
        let oneHeightSizeMargin = carenderSize(collectionViewHeight,section0Height: section0Height) % dayOfMonthLineNumber()
        let oneHeightSizePlus = oneHeightSize(collectionViewHeight,section0Height: section0Height) + oneHeightSizeMargin
        return oneHeightSizePlus
        
    }
}


CustomCell.swiftを開く、書いてあったプログラムを削除し以下のコードを貼り付ける

cellDel

cellWri

CustomCell.swift
import UIKit

/* 日付を表示 */
class CustomCell: UICollectionViewCell {
    
    @IBOutlet weak var dayLabel: UILabel!
    
    override init(frame: CGRect){
        super.init(frame: frame)
    }
    
    required init(coder aDecoder: NSCoder){
        super.init(coder: aDecoder)!
    }
}


Color.swiftを開く、書いてあったプログラムを削除し以下のコードを貼り付ける

colorDel
colorWri

Color.swift
import UIKit

extension UIColor {
    
    //lightBlue
    class func lightBlue() -> UIColor {
        return UIColor(red: 92.0 / 255, green: 192.0 / 255, blue: 210.0 / 255, alpha: 1.0)
    }
    
    //lightRed
    class func lightRed() -> UIColor {
        return UIColor(red: 195.0 / 255, green: 123.0 / 255, blue: 175.0 / 255, alpha: 1.0)
    }
    
    //lightGray
    class func lightGray() -> UIColor {
        return UIColor(red: 140.0 / 255, green: 140.0 / 255, blue: 140.0 / 255, alpha: 1.0)
    }
    
    //WhiteGray
    class func WhiteGray() -> UIColor {
        return UIColor(red: 231.0 / 255, green: 232.0 / 255, blue: 226.0 / 255, alpha: 1.0)
    }
    
    //lightGreen
    class func lightGreen() -> UIColor {
        return UIColor(red: 218.0 / 255, green: 255.0 / 255, blue: 250.0 / 255, alpha: 1.0)
    }
    
}



関連記事

  1. swift

    【swift2.2】初心者がswiftで作ったカレンダーアプリ ~目次~

    カレンダーを表示するシンプルなアプリを作ります。G…

  2. swift

    【swift3.0】MIDIファイルを再生させる

    swift3.0でMIDIファイルを再生させます。…

  3. swift

    【swift3.0】MPVolumeView 縦スライダー操作中にシステム音量を表示させずに音量を変…

    縦スライダー操作中にシステム音量を表示させずに音量を変更させます。…

  4. swift

    【swift3】正規表現で特殊文字を検索して置換する

    正規表現で特殊文字を検索して置換します。環境・Ma…

  5. swift

    【swift2.2】初心者がswiftで作ったカレンダーアプリ ②Storyboardにパーツを配置…

    カレンダーを表示するシンプルなアプリを作ります。目次①プロ…

  6. swift

    【swift2.2】初心者がswiftで作ったカレンダーアプリ ⑥確認する

    目次①プロジェクトを作成②Storyboardにパーツを配置、…

カテゴリー

おすすめ記事

アーカイブ

PAGE TOP