本文由CocoaChina譯者培子翻譯自Raywenderlich
原文:iBeacons Tutorial with iOS and Swift

你曾經(jīng)想過(guò)用手機在一個(gè)大型建筑物中為自己定位嗎,比如購物中心,或者棒球場(chǎng)。
當然,GPS可以讓你得知自己身處哪一座建筑物里。但是如果想要在這些鋼筋混凝土堆砌而成的建筑中獲得精確的GPS信號,只能祝你好運了。你所需要的是內置在建筑物中一些設備,(通過(guò)它們)讓手機獲取確定你的位置。
iBeacon,我們來(lái)了!在這篇iBeacons教程中,將會(huì )開(kāi)發(fā)一個(gè)App,功能包括,紀錄已知的iBeacon發(fā)射器;還有當你的手機設備移出它的信號輻射范圍時(shí),App會(huì )提醒你。這個(gè)App的一大用處是:將iBeacon發(fā)射器放置在你的電腦包、錢(qián)包里,甚至綁在貓咪的項圈上,以及其他貴重物品上等。一旦設備移出iBeacon輻射范圍,App就會(huì )檢測到并且通知你。
如果想繼續深入,你需要一臺iOS設備和一個(gè)iBeacon設備。如果沒(méi)有iBeacon設備,但還有另外一個(gè)iOS設備,你也可以把它當作iBeacon設備來(lái)用。
開(kāi)始吧
目前有很多可用的iBeacon設備,在Google一搜一大堆。但是蘋(píng)果公司引進(jìn)iBeacon時(shí),他們還聲稱(chēng)任何兼容iOS的設備都能充當iBeacon。目前包括以下設備:
iPhone4s 或者 之后的iPhone設備
第三代iPad或者 之后iPad設備
iPad mini 或者 之后iPad mini設備
第五代iPod touch 或者之后iPod touch設備
備注:如果沒(méi)有單獨的iBeacon發(fā)射器,但擁有一臺支持iBeacons的iOS設備,你可以對照《what's new in core location of iOS 7 by Tutorials》書(shū)中第22章的描述,開(kāi)發(fā)一個(gè)充當iBeacon角色的App。
iBeacon就是一種低功耗藍牙設備,它能以特定的數據結構廣播數據信息。這些屬性雖然超出了本篇教程的討論范圍,但是對理解iOS能夠監測iBeacon設備很重要,這些設備廣播三個(gè)數據:UUID,major和minor。UUID是universally unique identifier的首字母縮寫(xiě),它是一個(gè)128位的值,通常以十六進(jìn)制的方式顯示:B558CBDA-4472-4211-A350-FF1196FFE8C8
在iBeacon的環(huán)境下,UUID用來(lái)表示設備的最高級別標識。
Major和minor值則是在UUID下提供更細微的辨別標識。它們的值用16位無(wú)符號整型數簡(jiǎn)單表示,用來(lái)識別單個(gè)iBeacon設備,即使這些設備有著(zhù)相同的UUID。
例如,你有多家百貨公司,打算讓所有的iBeacon設備發(fā)射相同的UUID信息,但是每家百貨公司擁有各自的major值,并且在每家百貨公司的各部門(mén)又擁有各自的minor值。這樣App就可以對放置在邁阿密的弗羅里達分店的鞋業(yè)部門(mén)的iBeacon設備做相應的信息反饋。
ForgetMeNot 開(kāi)始項目
從這兒下載工程啟動(dòng)文件,它的界面很簡(jiǎn)單,就是在表格視圖中添加和刪除對象。表格里的每一個(gè)對象代表一個(gè)iBeacon設備,在現實(shí)生活中,它可以代表你不想遺失的東西。
啟動(dòng)并構建App,你會(huì )看到一個(gè)空的列表,沒(méi)有任何對象。點(diǎn)擊+按鈕,為它添加新項,如下:

首屏
添加新項,你需要為新對象命名,還有與之對應的值??梢酝ㄟ^(guò)查看iBeacon的文檔來(lái)獲得它的UUID。立即添加進(jìn)去吧,或者用一些占位符值,如下:

點(diǎn)擊save按鈕,返回到列表界面,就會(huì )看到location顯示為Unknown的對象,如下:

想添加多少,就添加多少,或者刪掉已有的。NSUserDefaults會(huì )保存列表里的選項,以便再次打開(kāi)App時(shí)可用。
界面上,看上去也就那么回事;最有趣的部分藏在了表象之下。該App的獨特之處就在于表格里顯示的Item類(lèi)。
在Xcode中打開(kāi)Item.swift。該類(lèi)對應著(zhù)界面從用戶(hù)那里請求的信息,它遵循NSCoding協(xié)議,因此可以被串行和并行的存儲到硬盤(pán)上。
現在看一下AddItemViewController.swift。這是用來(lái)添加新Item對象的視圖控制器。除了對用戶(hù)輸入做了些驗證,確保用戶(hù)輸入有效的名稱(chēng)和UUID之外,它就是一個(gè)簡(jiǎn)單的UITableViewController。
一旦nameTextField和uuidTextField內容有效,右上角的Save按鈕就會(huì )變?yōu)榭牲c(diǎn)擊狀態(tài)了。
既然已經(jīng)熟悉了項目啟動(dòng)文件,你就能夠在你的工程中實(shí)現iBeacon了。
Core Location 許可
你的設備當然不會(huì )自動(dòng)監測iBeacon的,所以首先你得告知它。CLBeaconRegion類(lèi)代表一個(gè)iBeacon;CL前綴的類(lèi)表示它屬于Core Location框架。
iBeacon與Core Location關(guān)聯(lián)在一起看上去有點(diǎn)奇怪,因為它就是一個(gè)藍牙設備而已,但是也可以這么認為,那就是iBeacon提供小范圍定位功能,而GPS提供的是大范圍定位功能。當想讓iOS設備充當iBeacon時(shí),你還需要引入Core Bluetooth框架,但只想檢測iBeacon設備,你只需要Core Location就行了。
首先為Item引入CLBeaconRegion。
打開(kāi)Item.swift,在頂部添加如下代碼:
import CoreLocation
接下來(lái),更新majorValue和minorValue定義,并初始化如下:
let majorValue: CLBeaconMajorValuelet minorValue: CLBeaconMinorValue init(name: String, uuid: NSUUID, majorValue: CLBeaconMajorValue, minorValue: CLBeaconMinorValue) { self.name = name self.uuid = uuid self.majorValue = majorValue self.minorValue = minorValue}CLBeaconMajorValue?和?CLBeaconMinorValue都是UInt16型,用來(lái)表示major和minor值。
雖然它們的數據類(lèi)型一樣,但是為了提高Item的可讀性和增加數據的安全性,你最好不要把major和minor值搞混。
打開(kāi)ItemsViewController.swift,在頂部引入Core Location:
import CoreLocation
為其添加如下屬性:
let locationManager = CLLocationManager()
當引入Core Location功能時(shí),需要用到這個(gè)CLLocationManager對象。
然后,更新viewDidLoad(),如下:
override func viewDidLoad() { super.viewDidLoad() locationManager.requestAlwaysAuthorization() loadItems()}如果設備沒(méi)有給App授權,它就會(huì )調用requestAlwaysAuthorization()方法來(lái)提示用戶(hù)是否允許使用定位服務(wù)。在iOS8中,Always和When in Use是最新有關(guān)定位授權的狀態(tài)。在A(yíng)pp使用Always權限授權時(shí),只要app在前臺或者后臺處于運行狀態(tài),它就可以啟動(dòng)所有可用的定位服務(wù)。
因為該教程對iBeacon一直進(jìn)行區域監測,所以當app處于前臺或者后臺運行時(shí),需要Always定位許可來(lái)觸發(fā)區域事件。
iOS8要求你在Info.plist?中設置一串字符,該字符串會(huì )在app請求定位服務(wù)時(shí)顯示出來(lái)。如果不設置它,定位服務(wù)就會(huì )無(wú)效,甚至都得不到任何警告!
打開(kāi)Info.plist,選中Information Property List 后,點(diǎn)擊+,添加新的一行。

遺憾的是,需要添加的key不是在下拉列表中預定義好的,需要自己輸入進(jìn)去。把key設置為NSLocationAlwaysUsageDescription,Type設為String類(lèi)型。然后輸入提示文字,告訴用戶(hù)用戶(hù)為何要開(kāi)啟定位服務(wù),例如:"ForgetMeNot would like to teach you how to use iBeacons!"

啟動(dòng)并構建app,一旦運行,你會(huì )看到一段消息,詢(xún)問(wèn)你是否允許app使用定位服務(wù):

允許訪(fǎng)問(wèn)位置
選擇Allow,app就能夠追蹤iBeacon設備了
監聽(tīng)iBeacon
現在app有了定位服務(wù)的授權,是時(shí)候搜索beacon設備了!在ItemsViewController.swift的底部添加類(lèi)extension,如下:
// MARK: - CLLocationManagerDelegate extension ItemsViewController: CLLocationManagerDelegate {}這段代碼表示ItemsViewController遵循CLLocationManagerDelegate協(xié)議。接著(zhù)在extension里添加委托方法,讓它們結合在一起。
在viewDidLoad方法最后一行添加如下代碼:
locationManager.delegate = self
設置CLLocationManager的委托對象為self,以便接收委托方法的回調。
有了CLLocationManager對象,你可以指導app使用CLBeaconRegion對一些指定的區域開(kāi)啟監測。當注冊了一個(gè)監控區域,之后只要啟動(dòng)app,這些區域就會(huì )存在下去。當你對一個(gè)交叉區域的邊界作出反應,而app沒(méi)有運行時(shí),這點(diǎn)很重要。
列表中的iBeacon對象由Item類(lèi)的items數組屬性表示。然而CLLocationManager希望你提供一個(gè)CLBeaconRegion對象來(lái)開(kāi)啟監控。
在ItemsViewController.swift中創(chuàng )建如下輔助方法:
func beaconRegionWithItem(item:Item) -> CLBeaconRegion { let beaconRegion = CLBeaconRegion(proximityUUID: item.uuid, major: item.majorValue, minor: item.minorValue, identifier: item.name) return beaconRegion}該方法通過(guò)提供的Item,返回一個(gè)CLBeaconRegion對象。
可以看出CLLBeaconRegion和Item之間有相似的數據結構,所以生成CLBeaconRegion對象很簡(jiǎn)單,因為它有直接對應的屬性UUID,major值和minor值
現在創(chuàng )建一個(gè)方法來(lái)監控已有的Item對象,給ItemsViewController添加如下代碼:
func startMonitoringItem(item: Item) { let beaconRegion = beaconRegionWithItem(item) locationManager.startMonitoringForRegion(beaconRegion) locationManager.startRangingBeaconsInRegion(beaconRegion)}該方法使用一個(gè)Item參數,調用之前定義的方法生成CLBeaconRegion。然后讓location manager開(kāi)始監控已有的區域,并在該區域內檢索iBeacon設備。
在給定的區域內,檢索就是發(fā)現iBeacon設備的過(guò)程,并確定iBeacon設備與iOS設備之間的距離。一臺接收到iBeacon發(fā)射信息的iOS設備能估算出它與iBeacon之間的距離。這個(gè)距離唄劃分為三個(gè)區域范圍:
Immediate 幾厘米之內
Near 幾米之內
Far 10米開(kāi)外
備注:Far,Near和Immediate對應的實(shí)際距離不是固定的,在Stack Overflow Question有提到它,并給它一個(gè)組略的距離范圍。
默認來(lái)講,無(wú)論app是否運行,只要你進(jìn)入或者走出監控區域,app都會(huì )通知你。另一方面,檢索iBeacon設備這一過(guò)程只會(huì )在app處于運行狀態(tài)時(shí)才會(huì )監測出區域距離。
還需要在某個(gè)Item區域被刪除時(shí),終止對它的監控。在ItemViewController添加如下代碼:
func stopMonitoringItem(item: Item) { let beaconRegion = beaconRegionWithItem(item) locationManager.stopMonitoringForRegion(beaconRegion) locationManager.stopRangingBeaconsInRegion(beaconRegion)}上述方法的作用剛好與startMonitoringItem方法相反,直到CLLocationManager終止監控和檢索活動(dòng)。
現在,已經(jīng)創(chuàng )建了開(kāi)始和終止方法,是時(shí)候用它們了!開(kāi)啟監控的正確時(shí)機是在用戶(hù)為列表添加新的item對象的時(shí)候。
看一下ItemsViewController中的saveItem(_:),該unwind segue轉場(chǎng)是在用戶(hù)點(diǎn)擊AddItemViewController的Save按鈕時(shí)觸發(fā),它同時(shí)生成了一個(gè)監控區域。在這個(gè)方法中找到調用persistItems()的那行,在它之前的一行添加如下代碼:
startMonitoringItem(newItem)
當用戶(hù)保存一個(gè)item對象時(shí),就會(huì )激活這個(gè)監控。同樣的,當啟動(dòng)app時(shí),app從NSUserDefaults加載已存的item對象,這也就意味著(zhù)啟動(dòng)的同時(shí)就需要開(kāi)啟對應的區域監控。
在ItemsViewController .swift中,找到loadItems(),在for循環(huán)中添加如下代碼:
startMonitoringItem(item)
這會(huì )確保每個(gè)item區域都處于受監控狀態(tài)。
還有,你需要關(guān)注一下從列表中刪除item。找到tableView(_:commitEditingStyle:forRowAtIndexPath:),在itemToRemove之后添加如下代碼:
stopMonitoringItem(itemToRemove)
當用戶(hù)刪除表視圖某行時(shí),就會(huì )調用這個(gè)委托方法?,F有的代碼處理的是將該行對象從數據模型和視圖上刪除,剛剛加的代碼將會(huì )終止對item監控。
此時(shí)此刻,你已經(jīng)完成了很多事情!app已經(jīng)有開(kāi)啟和終止對制定iBeacon的監控。
這個(gè)階段,可以啟動(dòng)并構建app了;但是盡管已經(jīng)注冊的iBeacon在你的app檢索范圍內,可是目前app無(wú)法對發(fā)現iBeacon設備作出任何反饋......還需要繼續完善它!
發(fā)現iBeacon的反饋
既然location manager已經(jīng)監控iBeacon,是時(shí)候通過(guò)CLLocationManagerDelegate的某些方法對iBeacon作出反應。
首先也是最重要的是錯誤處理,因為你正在處理設備指定的硬件信息,想知道監控或者檢索失敗的任何可能原因。
給ItemsViewController.swift里的CLLocationManagerDelegate的類(lèi)extension添加下面兩個(gè)方法:
func locationManager(manager: CLLocationManager!, monitoringDidFailForRegion region: CLRegion!, withError error: NSError!) { println("Failed monitoring region: \(error.description)")} func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) { println("Location manager failed: \(error.description)")}這些方法對監控iBeacon時(shí)接收的所有錯誤信息做一個(gè)簡(jiǎn)單記錄。
如果app一切運行正常,你不會(huì )看到這些方法的輸出信息。然而,如果某些地方出了問(wèn)題,很有可能從錯誤日志中獲得很有價(jià)值的信息。
下一步就是實(shí)時(shí)顯示iBeacon與iOS設備之間的距離。在CLLocationManagerDelegate的類(lèi)extension里,實(shí)現如下委托方法:
func locationManager(manager: CLLocationManager!, didRangeBeacons beacons: [AnyObject]!, inRegion region: CLBeaconRegion!) { if let beacons = beacons as? [CLBeacon] { for beacon in beacons { for item in items { // TODO: Determine if item is equal to ranged beacon } } }}這個(gè)委托方法會(huì )在iBeacon進(jìn)入監控范圍,或者移除監控范圍,或者iBeacon輻射范圍發(fā)生改變的時(shí)候被調用。
該app的目的就是使用由上述委托方法提供的iBeacon數組來(lái)更新列表的item對象,并顯示它們與設備的感應距離。重復迭代beacons數組,之后再迭代items數組,查看是兩者之間是否有匹配的部分。稍后來(lái)處理TODO部分代碼。
打開(kāi)item .swift,給Item類(lèi)添加如下屬性:
dynamic var lastSeenBeacon: CLBeacon
該屬性存儲的是最后一個(gè)與之匹配的CLBeacon對象,用來(lái)顯示距離信息。它有一個(gè)dynamic修飾符,以便于稍后對它使用key-value observation。
在Item.swift底部,在類(lèi)定義的外面,添加==操作符判斷如下代碼:
func ==(item: Item, beacon: CLBeacon) -> Bool { return ((beacon.proximityUUID.UUIDString == item.uuid.UUIDString) && (Int(beacon.major) == Int(item.majorValue)) && (Int(beacon.minor) == Int(item.minorValue)))}該等號操作符函數比較CLBeacon與Item對象,檢查它們是否相等--即,它們所有的標識是否匹配。這種情形下,如果UUID,major和minor值全部相同,那么CLBeacon與Item對象相等。
現在繼續完成檢索的委托方法,調用上述輔助方法。打開(kāi)ItemsViewController.swift,回到locationManager(_:didRangeBeacons:inRegion:)。替換for循環(huán)里的TODO部分,如下:
if item == beacon { item.lastSeenBeacon = beacon}這里,當發(fā)現一個(gè)item與iBeacon匹配時(shí),把它賦值給lastSeenBeacon。你會(huì )發(fā)現item和iBeacon受益于之前等號操作符函數!
是時(shí)候使用該屬性來(lái)顯示監測到的iBeacon設備與iOS設備之間的距離。
打開(kāi)ItemCell.swift,在didSet屬性觀(guān)察者起始部位,添加如下代碼:
item?.addObserver(self, forKeyPath: "lastSeenBeacon", options: .New, context: nil)
當為cell設置item時(shí),同樣要為lastSeenBeacon添加一個(gè)觀(guān)察者。為了保持平衡,還要在cell已經(jīng)設置過(guò)了item時(shí),刪除該觀(guān)察者。為didSet添加一個(gè)willSet屬性觀(guān)察者。確保它屬于item屬性:
willSet { if let thisItem = item { thisItem.removeObserver(self, forKeyPath: "lastSeenBeacon") }}這會(huì )確保只有一個(gè)item 對象被觀(guān)察。
當然,當cell被廢棄時(shí),同樣需要刪除觀(guān)察者。還在ItemCell.swift,添加如下代碼:
deinit { item?.removeObserver(self, forKeyPath: "lastSeenBeacon")}既然正在觀(guān)測距離的變化,你就可以在iBeacon的距離發(fā)生變化的時(shí)候通過(guò)一些邏輯規則來(lái)作出反饋。
每個(gè)CLBeacon對象都有一個(gè)proximity屬性,它是一個(gè)包含Far,Near,Immediate和Unknown的枚舉。
在ItemCell.swift中,為Core Location添加導入的申明:
import?CoreLocation
下一步,為ItemCell添加如下代碼:
func nameForProximity(proximity: CLProximity) -> String { switch proximity { case .Unknown: return "Unknown" case .Immediate: return "Immediate" case .Near: return "Near" case .Far: return "Far" }}該發(fā)放返回一個(gè)易讀的遠近值,后面會(huì )用到它。
接著(zhù),添加如下代碼:
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer) { if let anItem = object as? Item where anItem == item && keyPath == "lastSeenBeacon" { let proximity = nameForProximity(anItem.lastSeenBeacon!.proximity) let accuracy = String(format: "%.2f", anItem.lastSeenBeacon!.accuracy) detailTextLabel!.text = "Location: \(proximity) (approx. \(accuracy)m)" }}
每次lastSeenBeacon發(fā)生改變時(shí),都會(huì )調用這個(gè)方法,它會(huì )用CLBeacon的proximity值和accuracy值設置cell的detailTextLabel.text屬性。
后面這個(gè)accuracy的值即使你的iOS設備和iBeacon沒(méi)有移動(dòng),由于無(wú)線(xiàn)電頻率的緣故,也會(huì )一直浮動(dòng),因此不要指望它來(lái)達到beacon的精確定位。
現在確保已經(jīng)注冊了iBeacon,然后讓你的iOS設備逐漸靠近它,或者遠離它。當你移動(dòng)時(shí),你會(huì )看到標簽也會(huì )隨之更新,如下:

你會(huì )發(fā)現proximity和accuracy值受到iBeacon位置的影響比較劇烈;如果把它放在類(lèi)似箱子,包之類(lèi)的東西里,信號就會(huì )受到阻礙,這是因為iBeacon是低功耗設備,它的信號很容易被減弱。
記住這點(diǎn),在設計app時(shí),需要把iBeacon放置在最妥善的位置上。
推送
app看上去已經(jīng)很棒了;能顯示iBeacon設備,并且還能實(shí)時(shí)監控它們的距離。但是這還不是app的終極目標。當app沒(méi)有處于運行狀態(tài)時(shí),用戶(hù)忽略了他們的手提包,或者寵物貓跑丟了--更有甚者,貓和手提包都不翼而飛了!

他們是不是好可憐?
此刻,你可能注意到為app添加iBeacon功能不需要太多代碼。當貓貓和手提包都不見(jiàn)了時(shí),添加一個(gè)推送也一樣簡(jiǎn)單!
打開(kāi)AppDelegate .swift,導入CoreLocation,如下:
import CoreLocation
接著(zhù),讓AppDelegate遵循CLLocationManagerDelegate協(xié)議,在AppDelegate .swift底部添加如下代碼(在類(lèi)結束符下面)
// MARK: - CLLocationManagerDelegateextension AppDelegate: CLLocationManagerDelegate {}在這之前,你需要初始化location manager,設置它的delegate。
給AppDelegate添加一個(gè)locationManager屬性,用CLLocationManager對象實(shí)例化它:
let locationManager=CL LocationManager()
然后在application(_:didFinishLaunchingWithOptions:):添加如下代碼:
locationManager.delegate=self
要知道app中所有的location manager都能通過(guò)startMonitoringForRegion(_:)共同監控你添加的區域(location manager是單例)。因此最后一步,只需要在走出某個(gè)區域時(shí),對Core Location何時(shí)喚醒app作出反應就行了。
在AppDelegate.swift底部的類(lèi)extension里添加如下代碼:
func locationManager(manager: CLLocationManager!, didExitRegion region: CLRegion!) { if let beaconRegion = region as? CLBeaconRegion { var notification = UILocalNotification() notification.alertBody = "Are you forgetting something?" notification.soundName = "Default" UIApplication.sharedApplication().presentLocalNotificationNow(notification) }}當你走出某個(gè)區域,location manager就會(huì )調用上述方法,這是app一大亮點(diǎn)。假如離手提包越來(lái)越近,app就不需要提醒你,只有離它太遠才會(huì )觸發(fā)。
首先需要確定區域是否是CLBeaconRegion,因為當執行地理區域監控時(shí),它還有可能是CLCircularRegion。然后用"Are you forgetting something?"消息發(fā)一個(gè)本地推送。
在iOS 8之后,app使用本地推送或者遠程推送,必須注冊推送的類(lèi)型。系統給用戶(hù)權限來(lái)限制不同類(lèi)型推送的界面顯示。假如app不能使用這些推送類(lèi)型,即使它們是在推送載荷被指定過(guò),系統也不會(huì )對app icon標記,不會(huì )顯示提示信息,或者沒(méi)有提示音效。
在application(:_didFinishLaunchingWithOptions:):的最上面添加如下代碼:
let notificationType:UIUserNotificationType = UIUserNotificationType.Sound | UIUserNotificationType.Alertlet notificationSettings = UIUserNotificationSettings(forTypes: notificationType, categories: nil)UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
這段代碼就是當app收到一個(gè)推送時(shí),就會(huì )顯示一段提示信息,并且播放一段音效。
構建項目;確保app能監測到至少一個(gè)iBeacon設備,點(diǎn)擊Home按鈕讓app進(jìn)入后臺模式--這是現實(shí)生活中的場(chǎng)景,當你在處理其他事情的時(shí)候,比如處理Ray Wenderlich的另一個(gè)app時(shí),希望這個(gè)后臺app能通知你?,F在遠離iBeacon,一旦離得足夠遠,有就會(huì )收到這個(gè)推送,如下:

鎖屏上的通知
備注:蘋(píng)果系統以未公開(kāi)的方式延遲退出推送。這樣設計可能方便當你在區域范圍的邊緣游蕩或者iBeacon信號被干擾時(shí),app不會(huì )接收之前的推送。以筆者的經(jīng)驗來(lái)說(shuō),在iBeacon離開(kāi)區域范圍一分鐘時(shí)推送就會(huì )退出。
更進(jìn)一步?
還沒(méi)有為你的代碼綁定iBeacon嗎?從這兒下載最終的項目(here),教程所說(shuō)的全在這里。
你已經(jīng)有了一款很有用的app,來(lái)監控哪些比較難追蹤的東西。加一些額外的思考和編程功底,你還可以給app添加更多有用的功能:
通知用戶(hù)那個(gè)iBeacon移出了監控范圍
重復推送,確保用戶(hù)能看到它
提醒用戶(hù)iBeacon何時(shí)又返回監控范圍
這篇iBeacons教程僅僅只是揭開(kāi)iBeacon所有功能的冰山一角。
iBeacon不局限于傳統app;你還可以在Passbook中使用它。比如,當你去看電影時(shí),可以提供Passbook通行證當作電影票。當顧客走到附近有iBeacon設備的檢票員面前時(shí),app自動(dòng)在iPhone上顯示電影票!
對本篇教程有任何疑問(wèn)或者意見(jiàn),或者你有與iBeacon相關(guān)的好點(diǎn)子,歡迎加入我們的討論!
聯(lián)系客服