2016년 2월 25일 목요일

테이블 뷰셀에 버튼 이벤트 처리 하기

테이블 뷰셀에 on/off 를 표시하는 버튼이 있다고 할때

동적 테이블뷰에 수많은 테이블 뷰 셀에 on/off를 처리 할려면 어떻게 해야 하나?

tableViewCell 클래스 코드에 evnent를 작성한다.??

물론 보여주기만 한다면 가능 하다.

outlet을 tableView.xib에서 tableViewCell 클래스로 버튼을 연결해서 이벤트코드를 작성 하면
보여주는 기능 만 처리 할때는 충분 하다.


하지만 이를 이용하는  TableViewController 에서 어떤 talbeViewCell이 on인지 off인지
어떻게 알아 차릴수가 있을까?

이렇게 접근하면 곤란 하다.

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
       cell.onoffButton.tag = indexPath.row
        cell.onoffButton.addTarget(self, action: "onoffButtonConnected:", forControlEvents: .TouchUpInside)
        
        return cell
}

위와 같이 onoffButton  (테이블뷰셀에 버튼) 에 tag 값을 해당 row의 indexPath.row로 설정 하고
이벤트 함수를  addTarget을 이용해서 걸어 준다.

    func onoffButtonConnected(sender : UIButton!) {
        sender.selected = !sender.selected
        
        if self.morningcalldata[sender.tag]["setting"] == "ON" {
           self.morningcalldata[sender.tag]["setting"] = "OFF"
        } else {
           self.morningcalldata[sender.tag]["setting"] = "ON"
        }
    }


이벤트 함수에서는 tag 값을 다시 index로 이용하여 데이터 처리까지 할 수 있다.

아카이브 파일을 이용한 swift key value 저장

알람 리스트를 저장한다고 해보자

오전 , 오후, 시간, 반복, 설정  이러한 key와 이에 대한 value

다음과 같은 key value 쌍으로 정의 하면

 ["ampm":"오전","time":"06:00","repeat":"월화수목금","setting":"OFF"],

이러한 데이터를 저장하는 swift의 데이터 형은 어떻게 선언 하는가

[String : String]

이러한 데이터를 array로 처리 하니 다음과 같은 타입이 된다.
 [[String: String]] 

이러한 데이터를 파일로 저장했다가 필요에 따라 로드 하고 변경이되면 저장 해야 한다.

NSKeyedUnarchiver, NSKeyedArchiver를 이용하여 저장 하고 불러 올수 있다.

사용자 경로 처리를 위한 helper 클래스
class Helper {
    
    static let sharedInstance = Helper()
    
    static func getDocumentsDirectory() -> NSString {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let documentsDirectory = paths[0]
        return documentsDirectory
    }
}




사용자 경로에서 moriningcall.archive로 저장을 하고 불러오는 코드는 대략 아래와 같다.

다음과 같이 어레이를 선언 한다.
var morningcalldata: [[Sting:String]]!


let filemgr = NSFileManager.defaultManager()
        
        let filename = Helper.getDocumentsDirectory().stringByAppendingPathComponent("morningcall.archive")
        if filemgr.fileExistsAtPath(filename) {
            morningcalldata = NSKeyedUnarchiver.unarchiveObjectWithFile(filename) as! [[String: String]]
        } else {
            //디폴트 데이터
            morningcalldata = [
                        ["ampm":"오전","time":"06:00","repeat":"월화수목금","setting":"OFF"],
                        ["ampm":"오전","time":"06:00","repeat":"월화수목금","setting":"OFF"],
                        ["ampm":"오전","time":"06:00","repeat":"월화수목금","setting":"OFF"],
                        ["ampm":"오전","time":"06:00","repeat":"월화수목금","setting":"OFF"],
                        ["ampm":"오전","time":"06:00","repeat":"월화수목금","setting":"OFF"]
                    ]
            //최초 save
            NSKeyedArchiver.archiveRootObject(morningcalldata, toFile: filename )
        }

2016년 2월 21일 일요일

swift로 특정일이 현재로 부터 몇일전 "5 days ago" 이런 문자열을 만들때.

몇일전
몇시간전
몇분전

등등...

이런 정보를 표시해야 하는 경우가 있다.

NSDate의 extension으로 다음과 같이 구현 한다음

이를 이용하면 가능 하다.

import Foundation

extension NSDate {
    func yearsFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.Year, fromDate: date, toDate: self, options: []).year
    }
    func monthsFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.Month, fromDate: date, toDate: self, options: []).month
    }
    func weeksFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.WeekOfYear, fromDate: date, toDate: self, options: []).weekOfYear
    }
    func daysFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.Day, fromDate: date, toDate: self, options: []).day
    }
    func hoursFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.Hour, fromDate: date, toDate: self, options: []).hour
    }
    func minutesFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.Minute, fromDate: date, toDate: self, options: []).minute
    }
    func secondsFrom(date:NSDate) -> Int{
        return NSCalendar.currentCalendar().components(.Second, fromDate: date, toDate: self, options: []).second
    }
    func offsetFrom(date:NSDate) -> String {
        if yearsFrom(date)   > 0 { return "\(yearsFrom(date))y"   }
        if monthsFrom(date)  > 0 { return "\(monthsFrom(date))M"  }
        if weeksFrom(date)   > 0 { return "\(weeksFrom(date))w"   }
        if daysFrom(date)    > 0 { return "\(daysFrom(date))d"    }
        if hoursFrom(date)   > 0 { return "\(hoursFrom(date))h"   }
        if minutesFrom(date) > 0 { return "\(minutesFrom(date))m" }
        if secondsFrom(date) > 0 { return "\(secondsFrom(date))s" }
        return ""
    }

}

사용하는 방법은 다음과 같다.

lastSportData.year, mont, day 값을 NSDate로 만들어서 현재 NSDate와의 몇일 차이인지 문자열을 만든다.

            let date = NSDate()
            let day = date.daysFrom(makedate(lastSportData.year, month: lastSportData.month, day: lastSportData.day))
            if day > 0 {
                agoLabel.text = "\(day)days ago"
            } else {
                agoLabel.text = "today"
            }




2016년 2월 15일 월요일

swift Array Filter 사용하기

swift 에서 key valeu를 저장 하는 Array를 TableView로 적잘한  cell에 UI 컴퍼넌트들과 연결 하여 데이터를 보여 주고 있다고 할 때

여러 리스트 중에 특정한 값 만을 표시 하는 경우가 있다.

예를 들어 결재 내역에서 point 라는 항목을 전체 표시
차감만 표시
적립만 표시

해야 하는 경우는

ex)

    var mileageData = [
        ["point":"save", "price":"7000", "datetime":"2016.01.08 16:50", "message":"관리자가 마일리지 부여"],
        ["point":"used", "price":"10000", "datetime":"2016.01.08 16:50", "message":"관리자가 마일리지 부여"],

    ]


여기서 point key의 save만 , used만을 필터 처리 하고 싶은 경우가 있다.


filter() 메소드를 이용하면 된다.


        if filterButtons[0].selected == true { //전체
            mileageData = mileageDataOrigin
            
        } else if filterButtons[1].selected == true { //적립
            mileageData = mileageDataOrigin.filter({
                $0["point"] == "save"
            })
        } else { //차감
            mileageData = mileageDataOrigin.filter({
                $0["point"] == "used"
            })
        }
        tableView.reloadData()

위 코드는 mileageDataOrigin 으로 부터 mileageData Array를 point 키의 값을 기준으로 
필터 처리를 하여 재구성 하는 코드이다.

tableView.relaodData()를 이용하여 테이블뷰의 데이터를 새로 갱신 하면 변경된 데이터가 표시 된다.