29、打造 Apple Watch 笔记应用:功能实现与交互优化

打造 Apple Watch 笔记应用:功能实现与交互优化

1. 实现新笔记创建与设备通信

首先要实现创建新笔记的功能,这和之前实现的创建文档方法类似,但有一处不同:成功创建文档后,调用 handleListAllNotes ,让 Apple Watch 接收更新后的文档列表。

接着,要让 WCSession 使用应用委托作为其委托,因为应用委托现在能接收并回复来自手表的消息。在 AppDelegate didFinishLaunchingWithOptions 方法中添加以下代码来设置并激活会话:

WCSession.default().delegate = self
WCSession.default().activate()

和在 Apple Watch 上一样,要配置 WCSession 以便在收到消息时能得到通知,同时调用 activateSession 开启两个设备间的双向通信。至此,iPhone 和 Apple Watch 就能相互通信了。

2. 构建 Apple Watch 用户界面

Apple Watch 应用由两个 WKInterfaceController 子类组成,一个显示笔记列表,另一个显示单条笔记内容。

2.1 重命名默认控制器

默认情况下,Xcode 模板有个名为 InterfaceController WKInterfaceController ,为了更好描述其用途,需要重命名:
1. 将 InterfaceController.swift 文件重命名为 NoteListInterfaceController.swift
2. 打开该文件,把 InterfaceController 类重命名为 NoteListInterfaceController

由于 Apple Watch 应用启动时会查找名为 InterfaceController 的接口控制器类,所以要更改设置:
1. 打开 Watch 扩展的 Info.plist 文件,找到 RemoteInterfacePrincipalClass 条目。
2. 将该条目从 $(PRODUCT_MODULE_NAME).InterfaceController 改为 $(PRODUCT_MODULE_NAME).NoteListInterfaceController

2.2 创建新的控制器类

创建控制第二个屏幕(显示笔记内容)的类,每个独立的接口控制器应是独立的类,以便每个屏幕能独立运行:
1. 打开文件菜单,选择 New→File
2. 在 watchOS 部分选择 Source 类别,选中 WatchKit class ,点击 Next
3. 将新类命名为 NoteInterfaceController ,并使其成为 WKInterfaceController 的子类。

2.3 设置故事板

设置 watchOS 应用使用的故事板:
1. 打开 Interface.storyboard 文件,找到接口控制器并选中。
2. 打开 Identity Inspector ,将其类从 InterfaceController 改为 NoteListInterfaceController
3. 打开 Attributes Inspector ,将其标题改为 Notes

3. 设计笔记列表界面

笔记列表会显示一系列笔记,在 watchOS 中用表格显示内容列表,表格的每行界面可按需定制。每行内容由自定义的行控制器控制,每种行需要新的行控制器类,这里只需继承通用的 NSObject 类:
1. 到对象库搜索表格,将其拖到接口控制器中,表格会填满屏幕宽度。
2. 创建行控制器类:
- 在辅助编辑器中打开 NoteListInterfaceController.swift
- 在文件底部添加 NoteRow 类:

class NoteRow : NSObject {
}
- 在大纲中选中行控制器,打开 `Identity Inspector`,将其类设置为 `NoteRow`。
- 打开 `Attributes Inspector`,将其标识符也设置为 `NoteRow`,用于填充表格内容。
- 在对象库搜索 `Label` 并拖到表格行中,选中新标签,将其文本设置为 `Note Name`。
4. 连接界面与代码

将界面与代码连接起来:
1. 按住 Control 键,从标签拖到 NoteRow 类,创建名为 nameLabel 的新出口。
2. 再次按住 Control 键,从大纲中的表格条目拖到 NoteListInterfaceController 类,创建名为 noteListTable 的新出口。

5. 更新表格内容

将更新表格的代码封装到 updateListWithNotes 方法中:

func updateListWithNotes(_ notes: [SessionManager.NoteInfo]) {
    // 检查笔记是否有变化,无变化则不做处理
    if notes == self.displayedNotes {
        return
    }
    self.noteListTable.setNumberOfRows(notes.count, withRowType: "NoteRow")
    for (i, note) in notes.enumerated() {
        if let row = self.noteListTable.rowController(at: i) as? NoteRow {
            row.nameLabel.setText(note.name)
        }
    }
    self.displayedNotes = notes
}

NoteListViewController 中添加 willActivate 方法,在界面控制器显示时获取笔记列表并更新表格:

override func willActivate() {
    SessionManager.sharedSession.updateList() { notes, error in
        self.updateListWithNotes(notes)
    }
}

运行应用,笔记列表就会显示出来。

6. 显示笔记内容

创建显示单条笔记内容的新接口控制器,用户点击 NoteListInterfaceController 中的笔记时,通过 segue 过渡到该控制器,它会从 iPhone 请求笔记文本并显示在标签中。

6.1 创建新控制器界面
  1. 到对象库搜索 Interface Controller ,选择基础的 Interface Controller 拖入。
  2. 选中它,打开 Identity Inspector ,将其类从 WKInterfaceController 改为 NoteInterfaceController
  3. 打开 Attributes Inspector ,将其标题改为 Note
6.2 创建 segue
  1. 按住 Control 键,从表格视图中的单行拖到笔记接口控制器,释放鼠标后选择 Push 类型的 segue。
  2. 选中新 segue,打开 Attributes Inspector ,将其标识符改为 ShowNote
6.3 设计控制器界面
  1. 拖一个标签到接口控制器中。
  2. 打开 Attributes Inspector ,将 Lines 值设为 0,让标签能调整大小以适应所有文本。
  3. Text 值设为 Note Content ,运行时该文本会被实际笔记内容替换。
6.4 连接标签与代码

在辅助编辑器中打开 NoteInterfaceController ,按住 Control 键,从 Note Content 标签拖到 NoteInterfaceController 类,创建名为 noteContentLabel 的新出口。运行应用,点击笔记就会进入新界面。

6.5 传递笔记 URL

NoteListInterfaceController.swift 中添加 contextForSegue 方法:

override func contextForSegue(withIdentifier segueIdentifier: String,
    in table: WKInterfaceTable, rowIndex: Int) -> Any? {
    // 检查是否为 ShowNote segue
    if segueIdentifier == "ShowNote" {
        // 将选中笔记的 URL 传递给接口控制器
        return SessionManager.sharedSession.notes[rowIndex].URL
    }
    return nil
}

NoteInterfaceController.swift 中更新 awakeWithContext 方法:

override func awake(withContext context: Any?) {
    // 希望接收到指向 iPhone 上笔记的 NSURL
    if let url = context as? URL {
        // 先清空标签
        self.noteContentLabel.setText(nil)
        SessionManager.sharedSession.loadNote(url,
            completionHandler: { text, error -> Void in
            if let theText = text {
                // 显示笔记文本
                self.noteContentLabel.setText(theText)
            }
        })
    }
}
7. 处理错误情况

awakeWithContext 方法中添加错误处理代码:

override func awake(withContext context: Any?) {
    // 希望接收到指向 iPhone 上笔记的 NSURL
    if let url = context as? URL {
        // 先清空标签
        self.noteContentLabel.setText(nil)
        SessionManager.sharedSession.loadNote(url,
            completionHandler: { text, error -> Void in
            if let theError = error {
                // 显示错误提示
                let closeAction = WKAlertAction(title: "Close",
                    style: WKAlertActionStyle.default,
                    handler: { () -> Void in
                        self.pop()
                    })
                self.presentAlert(withTitle: "Error loading note",
                    message: theError.localizedDescription,
                    preferredStyle: WKAlertControllerStyle.alert,
                    actions: [closeAction])
                return
            }
            if let theText = text {
                // 显示笔记文本
                self.noteContentLabel.setText(theText)
            }
        })
    }
}

运行应用,若显示笔记内容出错,会弹出警告框。

8. 创建新笔记功能

通过菜单项实现 Apple Watch 上创建新笔记的功能,用户用力按压笔记列表屏幕,会出现创建新笔记的按钮,点击后可听写文本,完成后 NoteListInterfaceController 会将文本发送到 iPhone 创建笔记。

8.1 创建菜单项
  1. 打开 Interface.storyboard 文件。
  2. 在对象库搜索 Menu 并拖到 NoteListInterfaceController 上。
  3. 选中默认菜单项,打开 Attributes Inspector
  4. 将其图像设置为 Add ,标题设置为 Create Note
  5. 按住 Control 键,从菜单项拖到 NoteListInterfaceController ,创建名为 createNote 的新动作。
8.2 实现创建笔记方法

createNote 方法中添加以下代码:

@IBAction func createNote() {
    let suggestions = [
        "Awesome note!",
        "What a great test note!",
        "I love purchasing and reading books from O'Reilly Media!"
    ]
    self.presentTextInputController(withSuggestions: suggestions,
        allowedInputMode: WKTextInputMode.plain) {
        (results) -> Void in
            if let text = results?.first as? String {
                SessionManager
                    .sharedSession
                    .createNote(text, completionHandler: { notes, error in
                    self.updateListWithNotes(notes)
                })
            }
    }
}

运行应用,用力按压笔记列表开始听写,完成后会创建新笔记。

9. 添加手表与 iPhone 之间的接力功能

添加从 Apple Watch 到 iPhone 的接力功能,用户在手表上查看笔记时打开 iPhone,屏幕左下角会出现接力图标,向上滑动图标,文档会在 iOS 应用中打开。

9.1 添加接力相关代码
  1. 打开 DocumentCommon.swift 文件,添加以下代码:
let WatchHandoffDocumentURL = "watch_document_url_key"
  1. 打开 DocumentListViewController.swift ,在 restoreUserActivityState 方法中添加代码:
override func restoreUserActivityState(_ activity: NSUserActivity) {
    // 被告知打开文档
    if let url = activity.userInfo?[NSUserActivityDocumentURLKey] as? URL {
        // 打开文档
        self.performSegue(withIdentifier: "ShowDocument", sender: url)
    }
    // 来自手表的接力
    if let urlString = activity
            .userInfo?[WatchHandoffDocumentURL] as? String,
        let url = URL(string: urlString) {
        // 打开文档
        self.performSegue(withIdentifier: "ShowDocument", sender: url)
    }
    // 来自搜索结果
    if let searchableItemIdentifier = activity
            .userInfo?[CSSearchableItemActivityIdentifier] as? String,
        let url = URL(string: searchableItemIdentifier) {
        // 打开文档
        self.performSegue(withIdentifier: "ShowDocument", sender: url)
    }
}
9.2 广播用户活动

NoteInterfaceController.swift awakeWithContext 方法中添加代码:

override func awake(withContext context: Any?) {
    // 希望接收到指向 iPhone 上笔记的 NSURL
    if let url = context as? URL {
        // 先清空标签
        self.noteContentLabel.setText(nil)
        let activityInfo = [WatchHandoffDocumentURL: url.absoluteString]
        // 注意此字符串需与 iOS 和 Mac 应用 Info.plist 中定义的活动类型相同
        updateUserActivity("au.com.secretlab.Notes.editing",
            userInfo: activityInfo, webpageURL: nil)
        SessionManager.sharedSession.loadNote(url,
            completionHandler: { text, error -> Void in
            if let theError = error {
                // 显示错误提示
                let closeAction = WKAlertAction(title: "Close",
                    style: WKAlertActionStyle.default,
                    handler: { () -> Void in
                        self.pop()
                    })
                self.presentAlert(withTitle: "Error loading note",
                    message: theError.localizedDescription,
                    preferredStyle: WKAlertControllerStyle.alert,
                    actions: [closeAction])
                return
            }
            if let theText = text {
                // 显示笔记文本
                self.noteContentLabel.setText(theText)
            }
        })
    }
}

在 Apple Watch 上运行应用并打开笔记,打开 iPhone 就能看到接力图标,滑动图标文档会在 iOS 应用中打开。

以下是部分操作流程的 mermaid 流程图:

graph LR
    A[创建新笔记] --> B[用力按压笔记列表屏幕]
    B --> C[出现创建笔记按钮]
    C --> D[点击按钮听写文本]
    D --> E[NoteListInterfaceController 发送文本到 iPhone]
    E --> F[创建新笔记]

打造 Apple Watch 笔记应用:功能实现与交互优化

10. 功能总结与关键操作回顾

为了更清晰地展示整个笔记应用的功能和操作流程,我们对前面的内容进行总结,以下是关键功能及对应操作步骤的表格:
| 功能 | 操作步骤 |
| — | — |
| 创建新笔记 | 1. 用力按压笔记列表屏幕;2. 点击“Create Note”按钮;3. 选择建议文本或听写内容;4. 完成后自动创建新笔记并更新列表 |
| 显示笔记列表 | 应用启动时自动请求 iPhone 上的笔记列表并显示 |
| 查看笔记内容 | 1. 在笔记列表中点击某条笔记;2. 通过 segue 过渡到新界面;3. 自动请求并显示笔记内容 |
| 接力功能 | 1. 在 Apple Watch 上打开笔记;2. 打开 iPhone,屏幕左下角出现接力图标;3. 向上滑动图标,在 iOS 应用中打开文档 |

11. 代码结构与逻辑梳理

整个应用的代码结构和逻辑可以通过以下 mermaid 流程图来梳理:

graph LR
    A[App 启动] --> B[设置 WCSession]
    B --> C[显示笔记列表界面]
    C --> D[请求笔记列表]
    D --> E[更新笔记列表]
    C --> F[用户点击笔记]
    F --> G[传递笔记 URL]
    G --> H[显示笔记内容界面]
    H --> I[请求笔记内容]
    I --> J[显示笔记内容]
    C --> K[用户用力按压屏幕]
    K --> L[显示创建笔记菜单]
    L --> M[输入笔记内容]
    M --> N[发送内容到 iPhone 创建笔记]
    N --> E
    H --> O[接力功能触发]
    O --> P[传递文档 URL]
    P --> Q[在 iOS 应用中打开文档]
12. 常见问题与解决方案

在开发和使用过程中,可能会遇到一些常见问题,以下是部分问题及对应的解决方案:
| 问题 | 解决方案 |
| — | — |
| 接力功能在模拟器上无法使用 | 接力功能仅在物理设备上可用,需要在实际的 Apple Watch 和 iPhone 上进行测试 |
| 听写功能在模拟器上不工作 | 若要在模拟器上测试,需传递建议文本列表,而不是使用 nil,否则会直接进入听写模式,而模拟器不支持听写 |
| 显示笔记内容出错 | 在 awakeWithContext 方法中添加了错误处理代码,若出现错误会弹出警告框,可根据警告信息排查问题 |

13. 未来功能拓展方向

基于现有的笔记应用,我们可以考虑以下未来功能拓展方向:
1. 笔记编辑功能 :允许用户在 Apple Watch 上直接编辑笔记内容,而不仅仅是查看和创建。
2. 笔记分类与标签 :为笔记添加分类和标签,方便用户对笔记进行管理和查找。
3. 同步状态显示 :在界面上显示笔记的同步状态,让用户清楚知道哪些笔记已经同步到 iPhone。
4. 分享功能 :支持将笔记分享到其他应用或平台,如邮件、短信等。

14. 总结

通过一系列的操作和代码实现,我们成功打造了一个功能较为完善的 Apple Watch 笔记应用。从实现设备间的通信,到构建用户界面,再到添加各种功能如创建笔记、显示内容、接力等,每一步都有明确的操作步骤和代码示例。同时,我们也对可能遇到的问题提供了解决方案,并展望了未来的功能拓展方向。希望这些内容能帮助开发者更好地理解和开发 Apple Watch 应用。

在实际开发过程中,开发者可以根据自己的需求对代码和功能进行调整和优化,不断提升应用的性能和用户体验。相信通过不断的学习和实践,能够开发出更加优秀的 Apple Watch 应用。

【故障诊断】【pytorch】基于CNN-LSTM故障分类的轴承故障诊断研究[西储大学数据](Python代码实现)内容概要:本文介绍了基于CNN-LSTM神经网络模型的轴承故障分类方法,利用PyTorch框架实现,采用西储大学(Case Western Reserve University)公开的轴承故障数据集进行实验验证。该方法结合卷积神经网络(CNN)强大的特征提取能力和长短期记忆网络(LSTM)对时序数据的建模优势,实现对轴承不同故障类型和严重程度的高精度分类。文中详细阐述了数据预处理、模型构建、训练流程及结果分析过程,并提供了完整的Python代码实现,属于典型的工业设备故障诊断领域深度学习应用研究。; 适合人群:具备Python编程基础和深度学习基础知识的高校学生、科研人员及工业界从事设备状态监测故障诊断的工程师,尤其适合正在开展相关课题研究或希望复现EI级别论文成果的研究者。; 使用场景及目标:① 学习如何使用PyTorch搭建CNN-LSTM混合模型进行时间序列分类;② 掌握轴承振动信号的预处理特征学习方法;③ 复现并改进基于公开数据集的故障诊断模型,用于学术论文撰写或实际工业场景验证; 阅读建议:建议读者结合提供的代码逐行理解模型实现细节,重点关注数据加载、滑动窗口处理、网络结构设计及训练策略部分,鼓励在原有基础上尝试不同的网络结构或优化算法以提升分类性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值