標籤:內容 height 效果 連結 this eww lob containe http
EventKit為擷取和操作使用者日曆事件和提醒提供了一系列的類.在下面的教程中,我的目標是帶領你走出利用EventKit建立一個應用程式的第.我的目標是帶領你邁出利用EventKit建立一個應用程式的第一步.我將示範如何向使用者的日曆請求許可,我還將展示幾個處理使用者響應的例子(當他們授予存取權限,或者拒絕).
Example scenario
情境
讓我們先提出一個基本方案,作為本教程的例子。
假設我們正在構建一個應用程式,現在,有一個單一的視圖控制器。在得到使用者授權允許的情況下,我們希望這個視圖控制器顯示行事曆清單。如果使用者拒絕訪問,我們將向使用者展示一個訊息,用來說明我們的應用程式在沒有存取權限時不能運行,我們也將允許他們通過單擊一個按鈕能夠在他們的裝置的設定中設定授權訪問.
我已經建立一個那樣的應用程式作為例子–跳到GitHub中查看並研究這個例子的代碼.
Storyboard setup
故事面板設定
你使用EventKit的第一步就是需要為自己建立一個使用者介面來處理當你第一個程式啟動時使用者對”該程式可以訪問你的日曆嗎?”對出不同的響應,不久,我們將得到如何請求這個許可的詳情.但首先,讓我們來剖析我們如何用對於一個許可操作導致的給定響應能夠做正確的操作的一些視圖來安排我們的故事板.
使用者可以授予存取權限,也可以拒絕授予存取權限來通知他們的日曆或者提醒.我們需要為這兩種情況做好準備.
當被授予存取權限時,tableview顯示行事曆清單
我今天持樂觀態度,所以讓我們開始處理從一開始使用者就授予我們訪問他們日曆的許可權的情況.
當使用者授予我們存取權限,我們想列出一個表視圖的日曆.在接下來的教程中,我們將擔心資料來源的設定.現在,我們將從工具 + 生產力欄中拽一個表格視圖過來.
為了得到填滿整個螢幕的表視圖,我做了幾件事情.通常,當你從工具 + 生產力欄中拽一個表視圖過來的時候,它會在故事板中填滿整個情境.在布局中我向下拖頂部邊緣知道它”捕捉”到我所期望的狀態列底部被定位的那行.然後,我設定了以下限制:
我已經建立了一個設定表視圖的簡短截屏,如果你想要一個完整的練習,可以參看下面連結的內容:
這裡有這些約束的詳細視圖,以及故事板看起來像裝表視圖的視覺效果.
最後一點,在故事板中我已經將這個表視圖的hidden屬性設定為true.根據使用者允許或者拒絕對日曆的訪問後,我將切換表的可見度,但我認為值得指出的是在我例子中表視圖的初始狀態是被隱藏.
訪問被拒絕時的”需要許可”視圖
但有時,使用者拒絕授權訪問日曆,在意識到這樣做將導致基本上停止你應用程式所有的功能之前,如果你的整個應用程式或者只是該應用程式的一部分需要訪問功能,你需要一種方法來告知使用者,並為他們提供一種方法跳到使用者佈建,如果可能的話讓使用者手動授予存取權限.
我在樣本項目中的方法是在故事板情境中組織一個新的視圖,該視圖包含一個展示操作說明的標籤和一個點擊後使使用者進入我們應用程式的設定介面的按鈕.
再次,一些約束涉及到在運行時使一些事物正確的顯示.在這裡我不會講述這個細節,因為它很可能因為每一個執行操作而有一點不同.
我將指出的意見事情是,這個視圖的透明度已經被設定為0,以便如果使用者拒絕授權,我能夠展示一個逐漸消失的效果.下面就來看看在設定了隱藏“NeedPermissionsView”的情境:
Event Store的角色
EventKit的核心是EKEventStore.EKEventStore是事物的中心.建立EKEventStore的一個執行個體,為開發人員提供了對使用者的日曆和提醒列表中執行各種讀/寫操作的API.
一個與日曆互動的視圖控制器應該有一個引用EKEventStore的執行個體.這很容易被建立–這裡是一個例子:
1234 |
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let eventStore = EKEventStore() // ... } |
檢查日曆的授權
一旦我們有了引用EKEventStore的執行個體,我們可以做像檢查使用者是否授權訪問他們的日曆這樣的事情.根據這裡,我們可以做是否需要請求許可的決定,隨後確定要顯示的視圖(表視圖或者需要許可視圖).
我們在哪裡檢查日曆授權很重要.我的建議是每次在視圖出現時檢查(即在viewWillAppear()中),因為使用者首次授予存取權限,切換設定,拒絕訪問的情況是完全有可能的.我們的應用程式需要做出適當的響應.
In the example project provided with this article, I’ve created a function named checkCalendarAuthorizationStatus(). Here a peek at what it does:
在這個文章提供的樣本工程中,我已經建立了一個名為checkCalendarAuthorizationStatus()的函數.
接下來看看它的實現:
ViewController.swift
12345678910111213141516171819202122232425 |
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // ... override func viewWillAppear(animated: Bool) { checkCalendarAuthorizationStatus() } func checkCalendarAuthorizationStatus() { let status = EKEventStore.authorizationStatusForEntityType(EKEntityTypeEvent) switch (status) { case EKAuthorizationStatus.NotDetermined: // This happens on first-run requestAccessToCalendar() case EKAuthorizationStatus.Authorized: // Things are in line with being able to show the calendars in the table view loadCalendars() refreshTableView() case EKAuthorizationStatus.Restricted, EKAuthorizationStatus.Denied: // We need to help them give us permission needPermissionView.fadeIn() default : let alert = UIAlertView(title: "Privacy Warning" , message: "You have not granted permission for this app to access your Calendar" , delegate: nil, cancelButtonTitle: "OK" ) alert.show() } } // ... } |
這裡關鍵的功能是EKEventStore的 authorizationStatusForEntityType實現的.傳入的EKEntityTypeEvent用於跟使用者日曆進行互動.如果我們想要檢查他們的提醒的許可權,我們將在這裡使用EKEntityTypeReminder.
EKAuthorizationStatus的可能值根據switch裡的相應的case來執行封裝好的方便閱讀的獨立功能的邏輯代碼.
讓我們一步步來看一看這些功能.
請求訪問日曆
正如標題所說的,所有的事情從這裡開始.每當我們的應用程式載入和調用authorizationStatusForEntityType的時候,將返回NotDetermined的狀態.就是在這一點上我們想請求訪問日曆.
為了這樣做,按照下面的方法定義requestAccessToCalendar函數:
12345678910111213141516171819202122 |
requestAccessToCalendar() class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // … func requestAccessToCalendar() { eventStore.requestAccessToEntityType(EKEntityTypeEvent, completion: { (accessGranted: Bool, error: NSError!) in if accessGranted == true { // Ensure that UI refreshes happen back on the main thread! dispatch_async(dispatch_get_main_queue(), { self.loadCalendars() self.refreshTableView() }) } else { // Ensure that UI refreshes happen back on the main thread! dispatch_async(dispatch_get_main_queue(), { self.needPermissionView.fadeIn() }) } }) } // … } |
我們的EKEventStore執行個體提供了一個名為requestAccessToEntityType的函數.再次將EKEntityTypeEvent作為我們請求訪問日曆的參數傳遞.剩餘的有趣的部分在我們提供的封裝完的閉包裡能夠找到.
在實現裡有三個主要的事情需要注意:
傳遞到閉包裡的兩個參數一個是用來說明存取權限是否被授予的Bool類型的,另一個是NSError.
我們需要調用dispatch_async(),並表明我們要調回主隊列中執行重新整理UI的操作.
self.needPermissionView.fadeIn()作為我操作中的一個UIView的拓展,[Swift中漸入/淡齣動畫的拓展類(Fade In / Out Animations as Class Extensions in Swift)](https://github.com/andrewcbancroft/EventTracker/tree/ask-for-permission).
授予存取權限!載入日曆和重新整理表視圖
當被允許訪問的時候,我們可以調用eventStore執行個體中的calendarsForEntityType函數,並傳遞EKEntityTypeEvent去抓取使用者日曆的數組在我們的表視圖中顯示.下面就來看看:
1234567891011121314 |
loadCalendars() class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // ... var calendars: [EKCalendar]? // ... func loadCalendars() { self.calendars = eventStore.calendarsForEntityType(EKEntityTypeEvent) as? [EKCalendar] } func refreshTableView() { calendarsTableView.hidden = false calendarsTableView.reloadData() } // ... } |
拒絕訪問–顯示需要許可視圖
當訪問被拒絕的時候,我們需要彈出在故事板情境中建立的“Needs Permission View”.
在這個視圖中,上面的函數重新被調用,這樣有一個能夠讓使用者直接跳轉到我們應用程式的設定頁面中,以便他們能夠從那裡授權日曆訪問.這個按鈕連線到了一個IBAction.下面有實現IBAction的例子:
123456789 |
goToSettingsButtonTapped() class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // ... @IBAction func goToSettingsButtonTapped(sender: UIButton) { let openSettingsUrl = NSURL(string: UIApplicationOpenSettingsURLString) UIApplication.sharedApplication().openURL(openSettingsUrl!) } // ... } |
結束語
這幾乎完成了使用 Event Kit的開始工作!對於checkCalendarAuthorizationStatus()函數的其餘案例簡單的重用,我只是簡單的剖析了請求允許的過程.
我鼓勵你們跳到Github,並且作為你應用程式中利用Event Kit的開始,自己深入研究這些代碼.
Swift EventKit的初學者指南–請求許可權