• watchOS开发—初步认识


    Apple Watch

    初步了解

    • 简介
    • 项目演示
    • 创建项目
      • 简单的hello world
      • 项目结构
        • Extension:位于用户的iPhone安装了对应的App上,包含我们需要实现的代码逻辑和其他的资源文件
        • watch app:目前只允许包含storyboard文件和resource文件
        • InterfaceController:当前界面的控制器
          • 与UIViewController的区别是:InterfaceController最终继承的是NSObject
          • InterfaceController不会管理Watch APP的应用界面
          • Watch APP的界面是直接由Watch Kit来管理
        • NotificationController interface的通知控制器

    生命周期

    • apple Watch启动原理
      • 用户点击Watch APP后,与Watch匹配的iPhone会启动extension,然后与Watch建立连接,产生通信
    • NotificationController:
      • Watch OS提供了默认的通知显示,当用户点击通知进入APP时,就会调用以下两个方法
    	- (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)localNotification
    {
        
    }
    
    - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)remoteNotification
    {
        
    }
    - 通过这两个方法获得通知的消息,跳转到目标界面
    
    • 在NotificationController中可以实现以下两个方法
    - (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {
        
    }
    - (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {
        
    }
    - 获得通知内容,并设置处理完成的回调Block
    
    • apple Watch的生命周期方法
      • init:用来初始化interface Controller
      • awakeWithContext:类似UIViewController中的viewDidLoad方法,用来配置interface Controller
      • willActivity:界面将要显示给用户时会被调用,主要用来对试图进行一些小的调整,大规模的初始化还是放在init和awakeWithContext
      • didDeactivate:用来清空界面,程序进入不活动状态,可以用它来终止Timer或者来停止动画,这个方法不能再对界面进行操作
      • command + L锁定屏幕
    @implementation InterfaceController
    
    /**
     *  初始化当前控制器,子控制器不一定有值
     *
     *  @return 控制器
     */
    - (instancetype)init {
        if (self = [super init]) {
            NSLog(@"初始化当前控制器,子控制器不一定有值 %s %d", __func__, __LINE__);
        }
        return self;
    }
    
    /**
     *  创建界面完毕,可以在这个对子控制器赋值
     *
     *  @param context 界面里的内容
     */
    - (void)awakeWithContext:(id)context {
        [super awakeWithContext:context];
    
        // Configure interface objects here.
        NSLog(@"创建界面完毕,可以在这个对子控制器赋值 %s %d", __func__, __LINE__);
    }
    
    /**
     *   即将进入程序,对界面做微调,具体的初始化应该放在 init 或者 awakeWithContext
     */
    - (void)willActivate {
        // This method is called when watch view controller is about to be visible to user
        [super willActivate];
        
        NSLog(@"即将进入程序,对界面做微调,具体的初始化应该放在 init 或者 awakeWithContext %s %d", __func__, __LINE__);
    }
    
    /**
     *  清空界面,一般是用来停止动画:timer
     */
    - (void)didDeactivate {
        // This method is called when watch view controller is no longer visible
        [super didDeactivate];
        NSLog(@"清空界面,一般是用来停止动画:timer %s %d", __func__, __LINE__);
    }
    
    @end
    

    控件的基本使用

    • 标签

      • 属性:
        • installed:是否安装这个控件
        • horizontal:水平方向如何显示
        • vertical:垂直方向如何显示
        • size:
          • 自适应自身的宽高
          • 与当前的界面的等宽高
          • 设置固定宽高
        • adjustment:微调控件的值
      	- (void)awakeWithContext:(id)context {
      [super awakeWithContext:context];
      
      // Configure interface objects here.
      
      // 设置标签的文字
      [self.label setText:@"我是一个标签"];
      // 设置标签的文字颜色
      [self.label setTextColor:[UIColor redColor]];
      }
      
    • 按钮

      • 改变label的文字
      • 改变按钮的状态和文字
      • 按钮背景图片
      • 搭建界面

    • 代码实现
     - (void)awakeWithContext:(id)context {
        [super awakeWithContext:context];
    
        // Configure interface objects here.
        
        // 设置标签文字
        [self.label setText:@"文字已经被改变"];
        // 设置标签文字颜色
        [self.label setTextColor:[UIColor blueColor]];
        
        // 设置按钮不可点
        [self.button setEnabled:NO];
        // 设置按钮文字
        [self.button setTitle:@"不可dian"];
        // 设置按钮背景图片
        [self.button setBackgroundImage:[UIImage imageNamed:@"ad_00"]];
    }
    
    
    • 显示效果

    • 图片
      • 显示一张图片

    - 代码实现
    
    - (void)awakeWithContext:(id)context {
        [super awakeWithContext:context];
    
        // Configure interface objects here.
        [self.image setImageNamed:@"ad_01.png"];
    }
    
    • 显示效果

    计算器

    • 搭建界面

    • 监听事件
    • 计算

    控件的布局

    • group:一组是一个容器,它管理着在你的界面的其他视图的布局。可以指定背景颜色或图像来显示后面的组中的项目。
    • 综合小案例
      • 使用storyboard

    /**
     *  上
     */
    - (IBAction)up {
        
        // 设置动画时长2.0秒
        [self animateWithDuration:2.0 animations:^{
            // 设置控件 垂直方向的位置
            [self.ball setVerticalAlignment:WKInterfaceObjectVerticalAlignmentTop];
        }];
    }
    
    /**
     *  下
     */
    - (IBAction)down {
        
        [self animateWithDuration:2.0 animations:^{
            [self.ball setVerticalAlignment:WKInterfaceObjectVerticalAlignmentBottom];
        }];
    }
    
    /**
     *  左
     */
    - (IBAction)left {
        
        [self animateWithDuration:2.0 animations:^{
            // 设置控件 水平方向的位置
            [self.ball setHorizontalAlignment:WKInterfaceObjectHorizontalAlignmentLeft];
        }];
    }
    
    /**
     *  右
     */
    - (IBAction)rigth {
        
        [self animateWithDuration:2.0 animations:^{
            [self.ball setHorizontalAlignment:WKInterfaceObjectHorizontalAlignmentRight];
        }];
    }	
    

    控制器

    • 控制器的跳转
      • 使用storyboard
      • 使用代码的方式
    /**
     *  push方式跳转控制器
     */
    - (IBAction)push {
        /**
         *  name: 给控制器绑定一个Identifier:pushCtr
         */
        [self pushControllerWithName:@"pushCtr" context:nil];
    }
    
    /**
     *  moda方式跳转控制器
     */
    - (IBAction)moda {
        [self presentControllerWithName:@"modaCtr" context:nil];
    }
    
    
    • 控制器的创建

    图片浏览器

    • 通过nextpage
      • 界面搭建

    • 显示效果

    WKDevice

        // iOS
        UIDevice *device = [UIDevice currentDevice];
        
        // watch OS
        WKInterfaceDevice *interfaceDevice = [WKInterfaceDevice currentDevice];
        
        // 添加缓存图片 (过程中可能会添加失败)2
        [interfaceDevice addCachedImage:[UIImage imageNamed:@"ad_00"] name:@"Zeng01"];
        [interfaceDevice addCachedImage:[UIImage imageNamed:@"ad_01"] name:@"Zeng02"];
        
        /**
         *  会先判断图片是否子啊缓存区内,如果在,直接取出来使用
         *  如果不在缓存区,就创建一个名字为 ad_00 的图片
         *  每一个watch App 的缓存区最大不超过20M
         *  如果超过了20M,那么就一次从最开始的缓存图片开始删除,用来存放新的缓存图片
         */
        [self.showImage setImageNamed:@"ad_00"];
        
        
        // 从缓存区删除缓存图片
        [interfaceDevice removeCachedImageWithName:@"zeng02"];
        
        NSLog(@"所有的缓存图片 = %@", interfaceDevice.cachedImages);
        
        /**
         *  获取屏幕的大小
         *
         *  在42mm 的手表下  屏幕大小是 : 宽:156 高: 195   312 X 390 资源图片的像素
         *  在38mm 的手表下  屏幕大小是 :  宽:  136  高: 170    272 X 340 资源图片的像素
         */
        NSLog(@"当前屏幕的大小为 = %@, 当前屏幕可以缩放的比例 = %f", NSStringFromCGRect(interfaceDevice.screenBounds), interfaceDevice.screenScale);
    
    

    显示效果

    数据的共享

    // 数据共享
        // iOS
        NSUserDefaults *iOSDefaults = [NSUserDefaults standardUserDefaults];
        [iOSDefaults setObject:@"xmgShareData" forKey:@"xmgKey"];
        
        // watch OS
        // 1. 打开target中 app Groups  (iOS 上的  和 watch OS 上的)
            //1.1 打开成功之后 需要你写一个名字
        // 2. 使用以下方式创建数据库
        NSUserDefaults *watchOSDefaults = [[NSUserDefaults alloc]initWithSuiteName:@"group.xmg"];
        
        [watchOSDefaults setObject:@"网络太差" forKey:@"xmgKey"];
    
    

    其它控件

    • separator
    • switch
    • slider
    • date

    tableView

    • 界面搭建

    • 代码实现

    ShowCell.h

    
    @interface ShowCell : NSObject
    
    - (void)setImageName:(NSString *)imageName title:(NSString *)title;
    
    @end
    
    

    showCell.m

    #import "ShowCell.h"
    #import <WatchKit/WatchKit.h>
    
    @interface ShowCell ()
    
    @property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceImage *image;
    @property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceLabel *label;
    
    @end
    
    @implementation ShowCell
    - (void)setImageName:(NSString *)imageName title:(NSString *)title
    {
        [self.image setImageNamed:imageName];
        [self.label setText:title];
    }
    @end
    

    InterfaceController.m

    @interface InterfaceController()
    @property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceTable *tableView;
    
    @end
    
    
    @implementation InterfaceController
    
    - (void)awakeWithContext:(id)context {
        [super awakeWithContext:context];
    
        // Configure interface objects here.
        [self.tableView setNumberOfRows:5 withRowType:@"row1"];
        
        for (NSUInteger i = 0; i < 5; i++) {
            
            // 获取第i行的row
            ShowCell *cell = [self.tableView rowControllerAtIndex:i];
            // 赋值
            [cell setImageName:[NSString stringWithFormat:@"ad_0%d", i] title:[NSString stringWithFormat:@"第%d个", i + 1]];
        }
    }
    
    /**
     *  点击了某行tableView
     */
    - (void)table:(WKInterfaceTable *)table didSelectRowAtIndex:(NSInteger)rowIndex
    {
        ShowCell *cell = [self.tableView rowControllerAtIndex:rowIndex];
        NSLog(@"%s", __func__);
    }
    
    - (void)willActivate {
        // This method is called when watch view controller is about to be visible to user
        [super willActivate];
    }
    
    - (void)didDeactivate {
        // This method is called when watch view controller is no longer visible
        [super didDeactivate];
    }
    
    /**
     *  添加一行
     */
    - (IBAction)addRow {
        
        // 获取tableView的最后一行
        NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:self.tableView.numberOfRows];
        
        // 插入一行
        [self.tableView insertRowsAtIndexes:indexSet withRowType:@"row1"];
        // 滚到哪一行
        [self.tableView scrollToRowAtIndex:0];
    }
    
    
    /**
     *  删除一行
     */
    - (IBAction)deleteRow {
    
        // 获取tableView的最后一行
        NSIndexSet *lastIndexSet = [NSIndexSet indexSetWithIndex:self.tableView.numberOfRows - 1];
        // 删除最后一行
        [self.tableView removeRowsAtIndexes:lastIndexSet];
    }
    
    @end
    
    • 显示效果

    pickerView

    • 界面搭建

    • 代码实现
    @interface InterfaceController()
    @property (unsafe_unretained, nonatomic) IBOutlet WKInterfacePicker *listPicker;
    @property (unsafe_unretained, nonatomic) IBOutlet WKInterfacePicker *stackPicker;
    @property (unsafe_unretained, nonatomic) IBOutlet WKInterfacePicker *sequencePicker;
    
    @end
    
    
    @implementation InterfaceController
    
    - (void)awakeWithContext:(id)context {
        [super awakeWithContext:context];
    
        // Configure interface objects here.
        
        WKPickerItem *item1 = [[WKPickerItem alloc] init];
        item1.title = @"第1个";
        item1.contentImage = [WKImage imageWithImage:[UIImage imageNamed:@"ad_00"]];
        item1.caption = @"薯片真好吃";
        
        WKPickerItem *item2 = [[WKPickerItem alloc] init];
        item2.title = @"第2个";
        item2.contentImage = [WKImage imageWithImage:[UIImage imageNamed:@"ad_01"]];
        item2.caption = @"饼干真好吃";
        
        WKPickerItem *item3 = [[WKPickerItem alloc] init];
        item3.title =  @"第3个";
        item3.contentImage = [WKImage imageWithImage:[UIImage imageNamed:@"ad_02"]];
        item3.caption = @"水疗";
        
        WKPickerItem *item4 = [[WKPickerItem alloc] init];
        item4.title = @"第4个";
        item4.contentImage = [WKImage imageWithImage:[UIImage imageNamed:@"ad_03"]];
        item4.caption = @"汤真美味";
        
        WKPickerItem *item5 = [[WKPickerItem alloc] init];
        item5.title = @"第5个";
        item5.contentImage = [WKImage imageWithImage:[UIImage imageNamed:@"ad_04"]];
        item5.caption = @"餐厅";
        
        [self.listPicker setItems:@[item1, item2, item3, item4, item5]];
        [self.stackPicker setItems:@[item1, item2, item3, item4, item5]];
        [self.sequencePicker setItems:@[item1, item2, item3, item4, item5]];
    
    }
    
    
    • 界面显示

    Glance

    • 工程创建

    • 界面搭建

    • 运行选项

    alert

    • 界面搭建

    • 代码实现
    - (IBAction)showAlertView {
        
        WKAlertAction *doneAction = [WKAlertAction actionWithTitle:@"done" style:WKAlertActionStyleDefault handler:^{
            NSLog(@"done");
        }];
        
        WKAlertAction *destructiveAction = [WKAlertAction actionWithTitle:@"具有破坏性的" style:WKAlertActionStyleDestructive handler:^{
            NSLog(@"具有破坏性的");
        }];
        
        WKAlertAction *cancelAction = [WKAlertAction actionWithTitle:@"exit" style:WKAlertActionStyleCancel handler:^{
            NSLog(@"cancel");
        }];
        
        /**
         *  三种显示方式
         *  WKAlertControllerStyleAlert,
         *  WKAlertControllerStyleSideBySideButtonsAlert,
         *  WKAlertControllerStyleActionSheet,
         */
        
        // Action依次排序的
    //    [self presentAlertControllerWithTitle:@"Demo" message:@"Action依次排序的" preferredStyle:WKAlertControllerStyleAlert actions:@[doneAction, destructiveAction, cancelAction]];
        
        // 只需要两个Action 一个Action就相当于一个按钮,否则报错
    //    [self presentAlertControllerWithTitle:@"Demo" message:@"只需要两个Action 一个Action就相当于一个按钮,否则报错" preferredStyle:WKAlertControllerStyleSideBySideButtonsAlert actions:@[doneAction, cancelAction]];
        
        // 退出在左上角
        [self presentAlertControllerWithTitle:@"Demo" message:@"退出在左上角" preferredStyle:WKAlertControllerStyleActionSheet actions:@[doneAction, destructiveAction, cancelAction]];
    }
    
    • 显示效果

      • 初始化界面

      • WKAlertControllerStyleAlert

      • WKAlertControllerStyleSideBySideButtonsAlert

      • WKAlertControllerStyleActionSheet

    动画

    • 渐变动画

    • 平移动画

    • hidden动画

    • 形变动画

      • 界面搭建

      • 代码实现
    	/**
     *  上移
     */
    - (IBAction)moveUp {
        [self animateWithDuration:2.0f animations:^{
            [self.ball setVerticalAlignment:WKInterfaceObjectVerticalAlignmentTop];
        }];
    }
    
    /**
     *  下移
     */
    - (IBAction)moveDown {
        [self animateWithDuration:2.0f animations:^{
            [self.ball setVerticalAlignment:WKInterfaceObjectVerticalAlignmentBottom];
        }];
    
    }
    
    /**
     *  左移
     */
    - (IBAction)moveLeft {
        [self animateWithDuration:2.0f animations:^{
            [self.ball setHorizontalAlignment:WKInterfaceObjectHorizontalAlignmentLeft];
        }];
    
    }
    
    /**
     *  右移
     */
    - (IBAction)moveRight {
        [self animateWithDuration:2.0f animations:^{
            [self.ball setHorizontalAlignment:WKInterfaceObjectHorizontalAlignmentRight];
        }];
    }
    
    /**
     *  缩放
     */
    - (IBAction)MoveZoom {
        [self animateWithDuration:2.0f animations:^{
            [self.ball setRelativeWidth:0.8 withAdjustment:10];
            [self.ball setRelativeHeight:0.4 withAdjustment:10];
        }];
    }
    
    • 显示效果

        ![](http://images2015.cnblogs.com/blog/1002304/201608/1002304-20160820212018531-772209631.png)
      
        ![](http://images2015.cnblogs.com/blog/1002304/201608/1002304-20160820212025968-1691369795.png)
      
        ![](http://images2015.cnblogs.com/blog/1002304/201608/1002304-20160820212033453-588989304.png)
  • 相关阅读:
    Lua Coroutine详解
    Lua IO库详解
    vue 组件基本使用
    js 发送异步请求
    小程序保存图片到相册
    js 学习四 对象应用 吃货游戏
    js 学习三 Array
    js 学习二 字符串常用方法
    js 学习一 猜数字游戏
    phpmyadmin导入大容量.sql文件
  • 原文地址:https://www.cnblogs.com/zengshuilin/p/5791263.html
Copyright © 2020-2023  润新知