[iOS] 透過HealthKit獲取步數與距離
原本想透過智慧運動裝置來獲取步數與距離,可惜遲遲等不到韌體開發完成,只好暫且透過HealthKit獲取步數與距離!因為iPhone本身就有運動感測器,會自動算出步數與距離,然後寫入HealthKit,想做運動健康相關App,於是有數據來源可使用。
iOS 10開始之後要在info.plist設定Privacy。
原本想透過智慧運動裝置來獲取步數與距離,可惜遲遲等不到韌體開發完成,只好暫且透過HealthKit獲取步數與距離!因為iPhone本身就有運動感測器,會自動算出步數與距離,然後寫入HealthKit,想做運動健康相關App,於是有數據來源可使用。
iOS 10開始之後要在info.plist設定Privacy。
「看不到的不代表不存在~」,寫程式也會遇到這個現象!我在比較日期字串時,發現明明兩者都是2018-07-17,卻被判斷出不一樣!?
好在透過取得字串長度,才發現真有看不見的字元「\0」!
(lldb) po firmwareVersionLabel.text.length
32(lldb) po newVersionLabel.text.length
10
實際上2018-07-17只有10個字元,而韌體回傳卻有32個字元,於是知道後面看不到的字元共有22個。
先前已寫過[iOS] 列出資料夾裡的檔案名稱 (List Contents of Directory),然而現在想要以最後修改時間列出檔案名稱 (List Contents of Directory By Last Modification Date),直接來看程式碼:
/**
Theme: List Contents of Directory By Last Modification Date
IDE: Xcode 9
Language: Objective C
Date: 107/08/02
Author: HappyMan
Blog: https://cg2010studio.com/
*/
+(NSArray *)listFileAtPathSortedByModificationDate:(NSString *)folderPath
{
NSError* error = nil;
NSArray* filesArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error];
if(error != nil) {
NSLog(@"Error in reading files: %@", [error localizedDescription]);
return @[];
}
// sort by creation date
NSMutableArray* filesAndProperties = [NSMutableArray arrayWithCapacity:[filesArray count]];
for(NSString* file in filesArray) {
NSString* filePath = [folderPath stringByAppendingPathComponent:file];
NSDictionary* properties = [[NSFileManager defaultManager]
attributesOfItemAtPath:filePath
error:&error];
NSDate* modDate = [properties objectForKey:NSFileModificationDate];
if(error == nil)
{
[filesAndProperties addObject:[NSDictionary dictionaryWithObjectsAndKeys:
file, @"fileName",
modDate, @"lastModificationDate",
nil]];
}
}
// sort using a block
// order inverted as we want latest date first
NSArray* sortedFiles = [filesAndProperties sortedArrayUsingComparator:
^(id path1, id path2)
{
// compare
NSComparisonResult comp = [[path1 objectForKey:@"lastModificationDate"] compare:
[path2 objectForKey:@"lastModificationDate"]];
// invert ordering
if (comp == NSOrderedDescending) {
comp = NSOrderedAscending;
}
else if(comp == NSOrderedAscending){
comp = NSOrderedDescending;
}
return comp;
}];
return sortedFiles;
}
以我的範例取得:
<__NSArrayI 0x137459190>(
{
fileName = “2018-08-02 10:17:20~2018-08-02 10:19:20.ecg";
lastModificationDate = “2018-08-02 02:19:24 +0000″;
},
{
fileName = “2018-08-02 10:11:32~2018-08-02 10:13:32.ecg";
lastModificationDate = “2018-08-02 02:14:48 +0000″;
},
{
fileName = “2018-08-02 10:09:28~2018-08-02 10:11:28.ecg";
lastModificationDate = “2018-08-02 02:11:31 +0000″;
},
{
fileName = “2018-08-02 10:06:47~2018-08-02 10:08:47.ecg";
lastModificationDate = “2018-08-02 02:08:50 +0000″;
},
{
fileName = “2018-08-02 09:02:28~2018-08-02 09:04:28.ecg";
lastModificationDate = “2018-08-02 01:04:30 +0000″;
},
{
fileName = “2018-07-31 23:40:03~2018-07-31 23:42:03.ecg";
lastModificationDate = “2018-07-31 15:42:07 +0000″;
},
{
fileName = “2018-07-31 14:43:38~2018-07-31 14:45:38.ecg";
lastModificationDate = “2018-07-31 06:45:40 +0000″;
},
{
fileName = “2018-07-31 14:40:58~2018-07-31 14:42:58.ecg";
lastModificationDate = “2018-07-31 06:43:01 +0000″;
}
)
我所使用的整合開發環境是Xcode,每年更新都會釋出新的功能,來幫助開發人如我者更有效率地工作!2018年Xcode即將邁入第10版,這裡我想要來介紹主線程檢查器 (Main Thread Checker)。
回想2012年我還是個初學者的時候,還不知道主線程的重要性,以致於有時候發生不預期的反應,實在摸不著頭緒!基本上要記住,改變畫面的動作要在主線程實現,不然會發生什麼事?有時候有反應,有時候沒反應,這種狀況debug超級困難呢!
好在Xcode已經能從語法分析來得知,哪些程式碼會跑到非主線程,若改變畫面的元件在非主線程操作,Xcode就會有紫色的提示。上圖表示Label一定要在主線程使用 ([UILabel text] must be used from main thread only)。
最近在開發藍芽裝置相關iOS App,每次掃描藍芽裝置都會出現一大串裝置的清單,那就表示周圍有很多藍芽裝置。怎麼來區別裝置?透過名稱是最方便的辦法,然而有時候名稱會重複(多台同款筆電、智慧手環等),此時就需要再透過Mac Address來辨識。
然而開發iOS時卻發現沒有提供此功能!?直覺猜想是Apple為了保護用戶的隱私,所以將取得Mac的API隱藏起來,也就是說iOS 7之後就無法取得Mac Address,目前可以UUID的方式來替代。只是此UUID還滿神奇,每個iOS裝置掃到同一個藍芽裝置,都會有不一樣的UUID!老闆準備要測試時,每次問我那支是哪個「號碼」,我只能兩手一攤,「請你自己記住好嗎XD?」
而Android就可以直接取得Mac Address!該說它好棒棒,還是⋯⋯
自從iOS10開始,Apple整合並重構原本復雜的SDK,特別是本地推播 (Local Notification)和遠程推播 (Remote Notification),已經統合為專門處理的User Notifications Framework。
五年前(不小心透露年齡⋯⋯)我已介紹過Local Notification,文章可見:Remote/Local Notification。
整合過後,推播變得更好管理,於是我們要逐漸捨既舊有的實作習慣囉~
半年前透過人家寫好的藍芽裝置SDK,輕鬆愉快實現App各種功能,現在必須自己寫SDK這一層,也就是透過iOS SDK,來實現藍芽各種連線相關的功能。此刻,我來研究重連藍芽裝置。
使用核心藍牙(Core Bluetooth)框架,有三種方式可以重連一個外設。你可以:
取決於使用場景,你可能不想掃描發現相同的外設,每當你想重連它的時候。相反,你可能首先使用其他選項,嘗試重連。如圖所示,一個可能的重連工作流是嘗試每個選項。
總覺得看了這圖後,就能完全掌握實作的流程!
最近寫iOS App要跟低功耗藍芽連線,接著傳輸資料解碼後來分析。兩年前有碰藍芽體脂計,是看著韌體溝通協議來實作,兩年後的今天再一次依樣畫葫蘆,這次要搞的硬體是24小時配戴的「玩意兒」。
感謝網路上已有許多教學,學習藍芽只要拾人「芽」慧,就能快速上手!
HappyMan・迴響