用 Swift 開發一個 iOS 地域定向 App

地域定向(Geo targeting)是一種根據用戶的地理位置,如國家、地區、城市等來呈現不同內容的技術。地域定向有著廣泛的使用場景。假設你有一個老顧客,他跑到競爭對手的餐廳里用餐。我們可以向他(她)顯示一些特惠折扣的信息,他重新拉回到你的餐廳里來。如果一個用戶在過去數天內逛過多次汽車經銷店,很可能他想買張新車。這樣,我們就可以將我們的汽車廣告推送給他。這種有的放矢的廣告比隨機投放的廣告要有效得多吧。


在本文,我會演示如何在 iOS 上實現地域定向。我會介紹蘋果傳統的 CLRegion 類。我還將介紹如何對這種不常見的功能進行測試。我們還會演示如何實現複雜的跟蹤邏輯。最後,我將解釋如何創建你「自訂的」region,以及爲什麽要使用「自訂的」 region,它比起 CLRegion 來有什麽優點。通過地域定向,你可以開發出大量基於位置信息的創意 App。

geotarget-demo

Geo Targeting 項目

假設我們想記錄用戶所去過的餐廳。我們開始創建這個項目。首先,創建一個名為GeoTargetingSingle View Application類型的 Swift 項目。

打開 Main.storyboard,在 ViewController 中加入一個 Map View。為 Map View 創建一個 @IBOutlet 連接。編譯器會報一個錯,先不管它,待會我們再解決它。故事版這邊的事情暫時就這樣了,讓我們來編輯 ViewController.swift

首先引入蘋果的 MapKitCoreLocation框架。讓 ViewController 聲明對兩個相關協議的實現。最終, ViewController.swift 應該是這個樣子:

接下來要生成一份 locationManager 對象,並配置 mapView。

這些程式碼負責完成如下工作:

  1. 創建一份 locationManager 對象,用於偵測用戶位置的變化。
  2. 配置 locationManager 對象,例如,將它的 delegate 設為 ViewController,這樣就可以在 ViewController 內部跟蹤用戶位置並監控 region 事件。 同時,將定位精度設定為最佳精度。
  3. 配置 mapView。將 mapView 的 delegate 設置為 ViewController ,這樣我們就可以在 mapView 中畫出一些額外的東西。然後讓 mapView 顯示用戶的當前位置並使地圖隨用戶位置而動,這有助於我們知道用戶是否進入了某個 region 。你也可以通過故事板來設置 MapView 的 delegate 和 showsUserLocation,我們在程式碼中這樣做,無非是讓你更便於理解而已。
  4. 添加測試數據。setupData 方法稍後再介紹。

現在,應該可以跟蹤到用戶位置了。當然我們還需要詢問用戶以獲得必要的權限。我們在程式碼中會檢測用戶是否同意授予我們這些權限。

讓我們看一下這個方法。首先,我們在 viewDidAppear 方法而不是其它方法中檢查用戶授權狀態,是因為用戶有會去設置程序中修改授權,然後又回到 App。因此我們需要在這時重新對用戶授權狀態進行檢查。

在檢查授權狀態時:

  1. 如果第一次開啟 App,我們還沒有向用戶申請過權限,我們應當立即這樣做。之所以申請的是「Always」權限,是因為要使用CLRegion必須獲得「Always」權限。
  2. 如果用戶不同意授權,我們會告訴用戶,我們的 App 只有在獲得使用定位服務的權限之後才能很好地工作。 這裡我們調用了 showAlert(title: String) 方法,這是一個簡化方法,用 UIAlertController 來顯示一些信息,并帶有一個 「Cancel」 按鈕。後面會經常用到這個方法。
  3. 如果用戶同意了我們的權限申請,我們就可以開始啟動標準的位置更新服務了。

然後運行 App。這時,你就會覺得奇怪—— App 沒有彈出提示讓用戶同意使用位置服務的消息啊?我們還應當在 ...-Info.plist 文件中增加一個 key NSLocationAlwaysUsageDescription,并賦予它一個值,諸如「爲什麽 App 需要【總是】訪問你的位置服務」。這個 key 會在我們調用 requestAlwaysAuthorization() 方法的時候用到。如果不這樣做,系統會忽略一切關於位置的功能調用。這個 key 只是用於向用戶描述你的 App 使用用戶位置的用途。

加完這個 key 之後,再次運行 App。現在系統就會彈出一個消息框,提示用戶授權並顯示我們剛才添加的描述。

當然,除了前面提到的幾種狀態,位置授權狀態還有其它幾種。不過在這個 App 中,我們只需要最基本的幾種狀態就足矣。

接下來我們準備監控 region,首先需要添加 region。

讓我們逐行分析 setupData() 方法中的語句。

  1. 首先要檢查用戶設備當前是否支持 region 範圍監控。如果用戶禁止了位置服務,關閉了後台App 刷新,或者設備處於飛行模式,isMonitoringAvailableForClass 方法將返回 false。
  2. 爲了演示,我們創建了一個虛擬的餐廳位置。在我們的例子中這樣做是 OK 的,但在真實項目中,你應當專門為這個對象創建一個單獨的類。
  3. 然後創建一個 region,以便 App 對其進行監控。我們用餐廳的名字作為 region 的唯一標識,這是因為只有這樣我們才能識別用戶進入了哪個 region。這樣做還有一個好處,我們不需要為 CLRegion 創建強引用,而是將 region 的 identifier 保存起來就可以了。
  4. 爲了好看,我們在 region 的中央加了一顆大頭釘。
  5. 爲了好看,我們還在地圖上畫了一個圓圈,用於代表 region 所包含的範圍。
  6. MKMapViewDelegate 的委託方法中繪製這個圓圈。

項目創建完成。我們可以開始對 region 進行監控了。

蘋果的 CLRegion

在本文,我們使用地理學的 region 概念。蘋果的 CLRegion 是一個以固定座標為圓心、以指定半徑為半徑的圓形區域。因此,使用 CLRegion 我們只能監控圓形 region。接下來,我們編寫追蹤 region 的代碼。

這兩個方法用於通知用戶,他當前正在穿過 region 的邊界。我們用我們簡化的 alert 方法來提示用戶。這兩個方法只會在用戶穿過 region邊界(還要加上系統定義的一個緩衝距離)時觸發。緩衝距離的使用是爲了防止當用戶在靠近邊界時,系統在短時間內頻繁觸發大量的進入/退出事件。

同時,可以跟蹤的 region 數目是有限的。系統給每個 App 的限制是 20 個 region。如果你想跟蹤的 region 數超過了這個限制,你可以只跟蹤用戶當前位置最近的幾個 region。每當用戶的位置移動,就將較遠的 region 移除,而將用戶移動路徑上的新 region 添加到監控中。如果超過限制,location manager 會觸發 monitoringDidFailForRegion 方法,為了體驗更好,你可以在這個方法中進行必要的處理。

我們需要牢牢記住兩點:兩個委託方法,以及使用時的一些限制。

對於簡單的 region 而言,我們需要編寫的方法就這麼多。現在你可以打開車門,驅車駛過你設定的區域。哈,開個玩笑而已。其實我們有一種很方便的方法來測試我們的 App。

如何測試

這個方法使用了 Xcode 提供的功能。我們將用到一個 GPX 文件。GPX 是一個 XML 文件,使用了軟件開發中常見的 GPS 數據格式進行描述。看一個例子,你就明白了。

這個 GPX 中描述了位於我們 region 附近的 3 個點。Xcode會用它們逐一作為用戶移動的位置。移動的速度是一秒鐘一個點。請從這裡下載 my GPX file America.gpx。下載完畢后將它拖到你的項目中。

然後運行 App。回到 Xcode,打開 Debug Area,選擇「模擬位置」,然後選擇 America。回到模擬器,用戶的位置會開始移動。

geotarget-simulate-location

幾秒鐘后,你會看到提示 「enter Lorrenzillo’s」,又過幾秒,有會提示 「exit Lorrenzillo’s」。這樣,我們的 region 監控功能就完成了!

geotarget-demo-app

實現複雜的業務邏輯

在某些 App 來說,簡單的進入/退出事件就夠了。但如果你要跟蹤更複雜的邏輯呢?也許你想跟蹤用戶進入一個 region 后的時間,或者用戶進入 region 的平均速度。在這個簡單的例子里,我們會判斷用戶進入我們的餐廳后的停留時間是否足夠長,以此來判斷他是否是我們一個顧客,以便我們對他進行下一步的詢問。讓我們來修改代碼。

  1. 將用戶的進入時間保存到 NSDictionary。
  2. 這裡實現了添加/刪除進入時間。
  3. 在 Location manager 的委託方法 didUpdateLocations 中,我們可以檢查用戶是否在 region 中停留了足夠的時間。

  1. 假設用 10 秒鐘來識別是不是一個有效的顧客。同時,我們還需要一個變量,用於保存那些用戶已經停留了足夠長時間的 region,一旦完成所需工作后,我們再刪除這些 region。
  2. 遍歷所有當前正在監控的 region。
  3. 如果顧客已經停留了足夠長時間,我們向用戶顯示指定信息并將 region 標記為「準備刪除」。
  4. 刪除已經停留夠時間的 region。

你可以在 updateRegions 方法中實現任何複雜邏輯。

定製化 Region

不過,蘋果的 CLRegion 有幾個限制。其中一個限制是,如果 App 只有「While in Use」權限時,無法監控 region。但我們知道,有許多用戶非常介意電池的壽命,他們不希望你的 App 總是跟蹤他們的位置。這樣去和用戶解釋是行不通的:只要他們允許你的 App 「一直」訪問定位功能就能讓他們享受更完美人生。所以有時候你不得不僅在用戶使用你的 App 的時候才能監控 region。我建議創建“自己的”的 region 類,用它來實現和 CLRegion 一樣的介面和囘調方法。這樣,對於那些已經熟悉了 CLRegion 的開發者來說,你定製的 region 類會非常容易上手。

你可以用上述協議將 CLRegion 所提供的功能遷移到你“自己的”定製化類中。
CLRegion 的另一個限制是它只能跟蹤圓形區域。有時候我們想監控多邊形的區域(矩形、五角形等)或者橢圓區域。這同樣也可以用“定製化的類”的方式實現。你只要在 RegionDelegateProtocol 協議的 didEnterRegion 方法中檢查這些條件即可。

當然,沒必要隨時向用戶顯示一些提示信息。大部份時候,我們會保存這些數據用於以後的數據分析。

你可以在這裡下載完整的 Xcode 項目示例代碼。

譯者簡介:楊宏焱,CSDN 博客專家(個人博客 http://blog.csdn.net/kmyhy)。2009 年開始學習蘋果 iOS 開發,精通 O-C/Swift 和 Cocoa Touch 框架,開發有多個商店應用和企業 App。熱愛寫作,著有多本技術專著,包括:《企業級 iOS 應用實戰》、《iPhone & iPad 企業移動應用開發秘笈》、《iOS8 Swift 編程指南》,《寫給大忙人看的 Swift》(合作翻譯)等。

原文Building a Geo Targeting iOS App in Swift


<p>美國貨運業 TruckerPath 平台的 iOS程式開發員,持續學習關於手機和網絡的新知識並加以實踐運用。過去四年發表了超過10隻Apps,當中兩隻更被App Store選為精選推介。請到 LinkedIn 和 GitHub 與 Eugene 聯絡。</p>

blog comments powered by Disqus
訂閲電子報

訂閲電子報

AppCoda致力於發佈優質iOS程式教學,你不必每天上站,輸入你的電子郵件地址訂閱網站的最新教學文章。每當有新文章發佈,我們會使用電子郵件通知你。

已收你的指示。請你檢查你的電郵,我們已寄出一封認證信,點擊信中鏈結才算完成訂閱。

Shares
Share This