這篇文章其實早在8月份就寫出來了,一直沒發表出來,這期間也有好幾位朋友來問我關于 Apple watch 相關的問題。我也將這篇文章的 md 發給他們了,現在將這篇文章發表出來,讓更多想了解 Apple watch 開發的小伙伴能有一個簡單的入門吧。
相關文章文章推薦
喵神 WWDC15 Session筆記 - 30 分鐘開發一個簡單的 watchOS 2 app
Apple Watch和iOS App之間的通信&Apple Watch自定義Cell
Apple Watch音頻錄制,.wav轉換.mp3,獲取音頻文件時長
Apple Watch開發中遇到的那些問題(WatchOS 2)
配置
Glance以及Notification需要自己手動的配置,編輯它們的Scheme就可以了。
生命周期


界面初始化調用順序(OneController,TwoController)
push | modal |
---|---|
OneController init | OneController init |
OneController awakeWithContext: | OneController awakeWithContext: |
OneController willActivate | OneController willActivate |
OneController didAppear | OneController didAppear |
點擊事件之后...
push | modal |
---|---|
OneController willDisappear | TwoController init |
TwoController init | TwoController awakeWithContext: |
TwoController awakeWithContext: | OneController willDisappear |
TwoController willActivate | TwoController willActivate |
OneController didDeactivate | TwoController didAppear |
TwoController didAppear | OneController didDeactivate |
返回事件之后...
pop | dismiss |
---|---|
TwoController willDisappear | TwoController willDisappear |
OneController willActivate | OneController willActivate: |
TwoController didDeactivate | OneController didAppear |
OneController didAppear | TwoController didDeactivate |
生命周期總結:(摘抄至喵神的blog)
每個 WKInterfaceController 對象必然會被調用的生命周期方法有三個,分別是該對象被初始化時的-initWithContext:
,將要呈現時的 -willActivate
以及呈現結束后的 -didDeactivate
,同樣類比 UIViewController 的話,可以將它們理解為分別對應-viewDidLoad
,viewWillAppear:
以及 -viewDidDisappear:
我們一般在 -initWithContext: 和 -willActivate 中配置“視圖元素”的屬性,在 -didDeactivate 中停用像是 NSTimer 之類的會 hold 住 self 的對象。需要特別注意的是,在 -didDeactivate 中對“視圖元素”屬性進行設置是無效的,因為當前的 WKInterfaceController 已經非活躍。
關于界面控件布局
帶你玩- AppleWatch開發二:界面布局
帶你玩-AppleWatch開發四:Table視圖
一個控件只能對應一個action
tableView的點擊事件,注意不要去給cell拉線
#pragma mark - Table Row Select
-(void)table:(WKInterfaceTable *)table didSelectRowAtIndex:(NSInteger)rowIndex
{
NSLog(@"did select rowIndex = %i",rowIndex);
/** 設置傳指數據(正向傳指) */
NSDictionary *contextDic = @{@"PicName":@"picture",@"index":[NSNumber numberWithInteger:rowIndex]};
// [self presentControllerWithName:@"detail" context:contextDic];
[self pushControllerWithName:@"detail" context:contextDic];
}
MenuController
Apple watch獨有的,類似iPhone的3DTouch,也是根據重力感應來彈出菜單
經過測試,最多只能添加四個,不管添加多少個,只會顯示前4個。
導航方式(層級式,分頁式)
push或者Modal之后返回只有一個返回箭頭
注意點
針對 Watch 的開發不能使用代碼的方式。首先,所有的 WKInterfaceObject 對象都必須要設計的時候經由 StoryBoard 進行添加,運行時我們無法再向界面上添加或者移除元素 (如果有移除需要的,可以使用隱藏);其次 WKInterfaceObject 與布局相關的某些屬性,比如行高行數等,不能夠在運行時進行變更和設定。基本來說在運行時我們只能夠改變視圖的內容,以及通過隱藏某些視圖元素來達到有限地改變布局 (其他視圖元素會試圖填充被隱藏的元素)。
控制器跳轉
- (void)pushControllerWithName:(NSString *)name context:(nullable id)context;
- (void)presentControllerWithName:(NSString *)name context:(nullable id)context;
/** present多個控制器,類似next Page */
- (void)presentControllerWithNames:(NSArray<NSString*> *)names contexts:(nullableNSArray*)contexts;
控制器之間傳值
正向傳值
- (void)pushControllerWithName:(NSString *)name context:(nullable id)context;
- (void)presentControllerWithName:(NSString *)name context:(nullable id)context;
- (void)presentControllerWithNames:(NSArray<NSString*> *)names contexts:(nullableNSArray*)contexts;
在上面的三個方法中的末尾都有一個context:
參數,這個參數就是用于在我們跳轉控制器的時候傳值,這點比iOS端方便多了。
Segue傳值
//tableView
- (NSArray *)contextsForSegueWithIdentifier:(NSString *)segueIdentifier inTable:(WKInterfaceTable *)table rowIndex:(NSInteger)rowIndex {
return nil;//傳值內容
}
- (id)contextForSegueWithIdentifier:(NSString *)segueIdentifier {
return nil;//傳值內容
}
- (NSArray *)contextsForSegueWithIdentifier:(NSString *)segueIdentifier {
return nil;//傳值內容
}
//tableView
- (id)contextForSegueWithIdentifier:(NSString *)segueIdentifier inTable:(WKInterfaceTable *)table rowIndex:(NSInteger)rowIndex {
return nil;//傳值內容
}
數據接收
在控制器的awakeWithContext:
方法接收數據
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
NSLog(@"receive = %@",context);
// Configure interface objects here.
}
多媒體
MP3/MP4播放
//.mp3 or .mp4
NSURL *url = [[NSBundle mainBundle] URLForResource:@"Jennifer Lopez - Feel the Light" withExtension:@".mp3"];
NSDictionary *options = @{WKMediaPlayerControllerOptionsAutoplayKey:@YES};
[self presentMediaPlayerControllerWithURL:url options:options completion:^(BOOL didPlayToEnd, NSTimeInterval endTime, NSError * _Nullable error) {
if (error) {
NSLog(@"error = %@",error);
return ;
}
NSLog(@"endTime = %f",endTime);
}];
音頻錄制
Apple watch有自帶的錄音控制器,我們只需要配置好就可以。支持.wav, .mp4, and .m4a
格式
NSDictionary *recorderOptions = @{
/** 錄制好之后的標題 */
WKAudioRecorderControllerOptionsActionTitleKey:@"發送",
/** 是否自動錄制 */
WKAudioRecorderControllerOptionsAutorecordKey:@YES,
/** 時間 NSTimeInterval */
WKAudioRecorderControllerOptionsMaximumDurationKey:@30
};
[self presentAudioRecorderControllerWithOutputURL:_recorderUrl preset:WKAudioRecorderPresetHighQualityAudio options:recorderOptions completion:^(BOOL didSave, NSError * _Nullable error) {
NSLog(@"didSave = %@",didSave?@"YES":@"NO");
if (error) {
NSLog(@"error = %@",error);
}
}];
注意點:
OutputURL 這個URL不是沙盒URL,而是App Groups
的URL。
在模擬器上使用沙盒路徑,錄制播放都沒有問題。
但是,使用手表的話就會出現一錄音這個控制器就直接dismiss掉了。
App Groups 的路徑
/** Identifier 要跟App Groups 一致 */
NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.LaiYoung.NextPage1111"];
NSURL *fileUrl = [url URLByAppendingPathComponent:@"record.wav"];
相關文章 Apple Watch音頻錄制,.wav轉換.mp3,獲取音頻文件時長
Glance界面(沒有交互響應,點擊任何位置都會跳轉到應用內部)
這是一個類似簡介的東西
開始沒有選擇,如何新增一個Glance
,在storyboard拖一個Glance Interface Controller
,然后新增一個Scheme
,命名為ClanceXXX
,選擇Edit Scheme...
,Executable
選擇XXX Watch App.app
,Watch Interface則選擇對應的Glance,close即可
UI:Glance都是基于特定模版的,蘋果提供了一系列的模版,包括了屏幕頂部和底部的設計。在Glance Interface Controller Scene
的第四個選擇器選擇。
UI界面不能添加帶有事件操作性的控件,例如Button,Switch
等等,但是可以添加Label,Image
這樣的控件。避免使用table
和map
Notifications
Apple watch的通知有兩種,分別是short looks
和long looks

short looks:短版本
從上圖看,內容很簡單,一個App的icon,應用的名字,一條消息。 和
Glance
的UI界面一樣不能添加帶有操作性的控件。至于哪些能添加哪些不能添加,最直接的辦法就是拖一個控件到Static Notification interface controller
或者 Dynamic Notification interface controller
不報錯就說明這個控件是可以添加的。</br>

long looks:長版本,長版本相對于短版本來說多了不少東西
從上圖看首先它的UI是可以滾動的
將它分為3個部分,分別是sash
,content
,actions
sash:包括了應用的名稱和icon,這部分默認的顏色是透明的,可以自己自定義顏色(修改顏色,選擇Static Notification interface controller
的入口,第四個選擇器)
content:這部分就是推送的詳細內容
action:操作按鈕(最多可以添加4個),然后Dismiss按鈕是系統一直會有的,不需要我們添加
模擬long looks

我們創建好一個Apple watch應用或者為已有項目添加一個target的時候默認會選擇Notification Scene
,然后我們的Notification InterfaceController
就會是上面的樣子,可能和storyboard中的有點不一樣,上面的圖我是在官方文檔中找到的,可能官方還沒來的及更改吧。只要明白意思就好...
Static interface
是必須的,而dynamic interface
是可選的。
在推送到消息的時候一般默認都是選擇的dynamic interface,只有當dynamic interface
不可用、沒有足夠的電力保證顯示動態界面、明確指出不能用動態界面的時候才會顯示Static interface

配置自定義界面的類目(Category)
官方文檔 Notifications
相關文章 Notifications概述
關于審核:
關于Watch App審核,如果你選擇了某個功能,但沒有實現,那么一定會被拒絕的,大家注意一下這點,坑就來那里~
坑:
- 使用代碼設置圖片</br>
Apple watch和iPhone開發不一樣,所以圖片尺寸要求也不一樣
找到Apple watch的Assets.xcassets
選擇圖片之后點擊第三個選擇器Devices
勾選watchOS,會發現對于的2x/38 mm 2x/42 mm 2x
都 沒有圖片,所以導致代碼設置不會出來。 -
watchOS 2.0
不再支持App Groups
,watchOS 2.0可以使用WCSession
進行通訊,WCSession
具體怎么使用可以看我之前的這片文章 Apple Watch和iOS App之間的通信&Apple Watch自定義Cell
Error
Apple watch的Bundle versions string,short
和Bundle version
都要和iOS 里面的一致,不然會build fail
小技巧
- 修改controller title的顏色</br>
選擇要修改的控制器,右側的選擇器,選擇第一個選擇器下面的Global Tint
網絡請求
不要使用NSURLConnection send...
方法,應該使用NSURLSession
方法