2010年9月29日 星期三

iOS - Event Kit Framework

iOS 4.0 可以充許開發者去存取存iPhone裡的行事曆,
和通訊錄相同的行事曆的整個是用Core Foundation架構起來的是C 而不是Objective-C
Core Foundation是C, Foundation是Objective-C
但是兩者之間有很方便的轉換方法,其實就是直接cast,這個又叫做Toll-Free bridge
比如CFStringRef和NSString *要轉換就直接寫
CFStringRef cfString = xxxxxx;
NSString * objString =  (NSString *) cfString;
這樣就可以直接用objString來當成cfString的替身了
先介紹一下幾個重要的c structure在event kit 會用到的
CFGregorianDate : 標準的日曆表示法,含有年,月,日,時,分,秒。至於為什麼叫Gregorian 請參考
CFGregorianUnits : 表示一段時間,和CFGregorianDate有相同的結構,但沒有限制值的範圍。比如說在CFGregorianDate"時"的值不能超過24小時,但在CFGregorianUnits"時"的值就可以超過24小時,因為它代表的是一段時間
我們來直接來看一個按下去按鈕就新增自訂event的例子
-(IBAction) createEvent:(id)sender{
     NSLog(@"launched");
     EKEventStore * myEventStore = [[EKEventStore alloc] init];

     EKEvent * myEvent = [EKEvent eventWithEventStore:myEventStore];
     myEvent.title = @"Knowledage Convergence Meeting";

     CFGregorianDate gregorianStartDate, gregorianEndDate;
     CFGregorianUnits startUnits = {0, 0, 0, 1, 3, 0};
     CFGregorianUnits endUnits = {0, 0, 0, 1, 5, 0};
     CFTimeZoneRef timeZone = CFTimeZoneCopySystem();


     gregorianStartDate = CFAbsoluteTimeGetGregorianDate(
            CFAbsoluteTimeGetCurrent(), timeZone);

     gregorianStartDate.hour = 17;
     gregorianStartDate.minute = 55;
     gregorianStartDate.second = 10;

     gregorianEndDate = CFAbsoluteTimeGetGregorianDate(
     CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTimeGetCurrent(), timeZone, endUnits),
           timeZone);
     gregorianEndDate.hour = 17;
     gregorianEndDate.minute = 55;
     gregorianEndDate.second = 25;

     NSDate* startDate =  [NSDate     dateWithTimeIntervalSinceReferenceDate:CFGregorianDateGetAbsoluteTime(gregorianStartDate,     timeZone)];
     NSDate* endDate =  [NSDate dateWithTimeIntervalSinceReferenceDate:CFGregorianDateGetAbsoluteTime(gregorianEndDate, timeZone)];

     CFRelease(timeZone);

     myEvent.startDate = startDate;
     myEvent.endDate = endDate;
     myEvent.calendar = [myEventStore defaultCalendarForNewEvents];

     EKAlarm *myAlarm = [EKAlarm alarmWithAbsoluteDate:startDate];

     myEvent.alarms = [NSArray arrayWithObject:myAlarm];
     NSError *theError = nil;
     [myEventStore saveEvent:myEvent span:EKSpanThisEvent error:&theError];
     NSLog(@"error is %@", theError);
}

這個流程主要就是產生自己的EKEvent, 藍色的property都是必要的,除了alarms之外,EKEvent又必需要和 EKEventStore結合,因為event實體是EKEventStore給的,event裡的calendar也是EKEventStore給的,而EKEventStore實體的產生就只是用alloc, init方式。
其中最麻煩的就是startDate和endDate,輾轉要從 CFGregorianDate 或是  CFGregorianUnits而來
單看是要從 CFAbsoluteTimeGetGregorianDate產生還是要從 CFAbsoluteTimeAddGregorianUnits產生,不過記得一點,產生 CFGregorianDate 的實體之後可以從他的field,year, month, day, hour, minute, second 來設定絕對的時間就如墨綠色部分所示。
EKAlarm 可有可無,它是先和NSDate結合,再一起被設定到EKEvent

沒有留言:

張貼留言