实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)(1)

简介: 实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)

实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)


前提回顾

上一章节发布之后,有不少开发的童鞋评论:

本来好好的,经过上一章节的调整后就各个页面开始报错了?

这很正常,刚开始学习SwiftUI的时候,有时候改了一个参数,或者少了一个花括号,愣是找不到哪里写错了。

后面写多了就基本知道哪里需要调整,而且遇到Bug不可怕,就怕的是明明没有报错,而且是跟着项目教程来的,项目运行后就是没效果,也不知道哪里出错了。

找不到自己的薄弱点,这才是最可怕的。

因此不用太过于担心,本章我们将继续基于完成的ModelViewModel,来完成View相关的内容。

实战编程-首页

单条笔记

我们回到View文件夹下的ContentView视图,先从NoteListRow单条笔记视图开始调整。

单条笔记涵盖哪些交互逻辑?一个是点击单条笔记的时候打开编辑笔记弹窗,二是点击笔记右侧的“更多”按钮,唤起二次确认弹窗,并可进行操作删除。如下图所示:

image.png

在上一章搭建ViewModel功能的时候,我们说到对单条笔记进行操作需要获得笔记的ID,然后基于单条数据的ID进行操作。那么这里需要先获得笔记的ID,如下代码所示:

kotlin

复制代码

// 引用viewModel
    @EnvironmentObject var viewModel: ViewModel
    // 获得项目唯一ID
    var itemId: UUID
    // 从模型类中找ID
    var item: NoteModel? {
        return viewModel.getItemById(itemId: itemId)
    }

image.png

上述代码中,我们先使用@EnvironmentObject全局环境变量引入ViewModel类,并赋值给viewModel。

@EnvironmentObject是一个动态视图属性,为了无论任何时候可绑定对象发生改变时停用当前视图的属性。

紧接着,声明一个变量itemId,遵循UUID格式,作为要使用到的ID。之前我们使用@ObservedObject获得NoteItem模型类,这里我们使用ViewModel就可以弃用原来的这块内容了,直接声明一个变量item,并通过调用viewModel中的getItemById方法获得对应的笔记ID。

在获得笔记ID后,系统可能无法返回相关的数据内容,也就是参数为空的情况导致系统报错,因此我们使用“?”,当返回的参数值为空的时候,就可以使用默认值填充,避免系统奔溃。

说回正题,由于我们使用item替换了原来的noteItem,在下面视图对应的参数也需要调整,如下代码所示:

var body: some View {
        HStack {
            HStack {
                VStack(alignment: .leading, spacing: 10) {
                    Text(item?.writeTime ?? "")
                        .font(.system(size: 14))
                        .foregroundColor(.gray)
                    Text(item?.title ?? "")
                        .font(.system(size: 17))
                        .foregroundColor(.black)
                    Text(item?.content ?? "")
                        .font(.system(size: 14))
                        .foregroundColor(.gray)
                        .lineLimit(1)
                        .multilineTextAlignment(.leading)
                }
            }
            Spacer()
            // 更多操作
            Button(action: {
            }) {
                Image(systemName: "ellipsis")
                    .foregroundColor(.gray)
                    .font(.system(size: 23))
            }
        }
  }

image.png

上述代码中,替换单条笔记绑定的参数,使用item替换noteItem,替换如下:

  • noteItem.writeTime 替换为 item?.writeTime ?? ""
  • noteItem.title 替换为 item?.title ?? ""
  • noteItem.content 替换为 item?.content ?? ""

替换后,我们来实现两个基本功能,一个是点击笔记的时候,打开编辑笔记弹窗,如下代码所示:

var body: some View {
        HStack {
            HStack {
                VStack(alignment: .leading, spacing: 10) {
                    Text(item?.writeTime ?? "")
                        .font(.system(size: 14))
                        .foregroundColor(.gray)
                    Text(item?.title ?? "")
                        .font(.system(size: 17))
                        .foregroundColor(.black)
                    Text(item?.content ?? "")
                        .font(.system(size: 14))
                        .foregroundColor(.gray)
                        .lineLimit(1)
                        .multilineTextAlignment(.leading)
                }
            }
            //点击编辑
            .onTapGesture {
                self.viewModel.isAdd = false
                self.viewModel.showEditNoteView = true
            }
            Spacer()
            // 更多操作
            Button(action: {
                viewModel.showActionSheet = true
            }) {
                Image(systemName: "ellipsis")
                    .foregroundColor(.gray)
                    .font(.system(size: 23))
            }
        }
  }

image.png

上述代码中,我们在笔记内容的HStack横向容器中增加了onTapGesture,当点击笔记内容的时候,说明我们需要编辑笔记,这里需要更新isAdd是否新增笔记状态为false,然后更新showEditNoteView打开编辑笔记弹窗的触发条件为true。

当用户点击“更多”操作时,更新showActionSheet打开二次确认弹窗的触发条件为true。

然后我们完成打开编辑弹窗和打开删除的二次确认弹窗的操作,如下代码所示:

// 编辑笔记
        .sheet(isPresented: $viewModel.showEditNoteView) {
            //编辑笔记弹窗
        }
        // 删除笔记
        .actionSheet(isPresented: self.$viewModel.showActionSheet) {
            ActionSheet(
                title: Text("你确定要删除此项吗?"),
                message: nil,
                buttons: [
                    .destructive(Text("删除"), action: {
                        self.viewModel.deleteItem(itemId: itemId)
                    }),
                    .cancel(Text("取消")),
                ])
        }

image.png

上述代码中,我们使用sheet方法,绑定showEditNoteView打开编辑弹窗的触发参数,编辑笔记页面后面我们会和新建笔记页面功用,这里还没有修改,就先放着。

删除笔记的方法我们使用actionSheet弹窗,绑定showActionSheet打开删除二次确认弹窗触发参数,在ActionSheet弹窗内,我们设置好标题,以及删除按钮的操作,当点击删除的时候,调用viewModel中的deleteItem方法,指定单条笔记的itemId找到对应的笔记进行删除。

完成后,我们单条笔记部分,除了打开编辑弹窗,其他内容已经修改完成。

笔记列表

回到ContentView视图,我们修改了单条笔记的内容,因此笔记列表noteListView视图也需要调整,首先引入ViewModel,如下代码所示:

// 引用viewModel
    @EnvironmentObject var viewModel: ViewModel

image.png

紧接着,我们换一种方法实现笔记列表,如下代码所示:

// MARK: 笔记列表
    func noteListView() -> some View {
        List {
            ForEach(viewModel.noteModels) { noteItem in
                NoteListRow(itemId: noteItem.id)
            }
        }
        .listStyle(InsetListStyle())
    }

image.png

上述代码中,我们换成了使用func方式声明视图,这是另一种创建视图的方法,这样创建视图的好处是,我们需要声明的参数可以放在ContentView视图中,就不需要在每一个视图中声明。

笔记列表唯一的改动就是NoteListRow单条笔记遍历循环的时候,数组来源于viewModel中的noteModels,然后NoteListRow中的ID为noteItem中的ID


相关文章
|
3月前
|
人工智能 自然语言处理 前端开发
用通义灵码,从 0 开始打造一个完整APP,无需编程经验就可以完成
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。本教程完全免费,而且为大家准备了 100 个降噪蓝牙耳机,送给前 100 个完成的粉丝。获奖的方式非常简单,只要你跟着教程完成第一课的内容就能获得。
11435 17
|
3月前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。
|
3月前
|
监控 算法 iOS开发
深入探索iOS函数调用栈:符号化与性能调优实战
在iOS开发中,理解函数调用栈对于性能调优和问题排查至关重要。函数调用栈记录了程序执行过程中的函数调用顺序,通过分析调用栈,我们可以识别性能瓶颈和潜在的代码问题。本文将分享iOS函数调用栈的基本概念、符号化过程以及如何利用调用栈进行性能调优。
54 2
|
5月前
|
Web App开发 Java 视频直播
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP
对于软件、计算机等专业的毕业生,毕业设计需实现实用软件或APP。新颖的设计应结合最新技术,如5G时代的音视频技术。示例包括: 1. **短视频分享APP**: 集成FFmpeg实现视频剪辑功能,如添加字幕、转场特效等。 2. **电商购物APP**: 具备直播带货功能,使用RTMP/SRT协议支持流畅直播体验。 3. **同城生活APP**: 引入WebRTC技术实现可信的视频通话功能。这些应用不仅实用,还能展示开发者紧跟技术潮流的能力。
107 4
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP
|
5月前
|
Swift iOS开发 UED
揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【9月更文挑战第5天】本文通过具体案例介绍如何在iOS应用中使用Swift与UIKit实现自定义按钮动画,当用户点击按钮时,按钮将从圆形变为椭圆形并从蓝色渐变到绿色,释放后恢复原状。文中详细展示了代码实现过程及动画平滑过渡的技巧,帮助读者提升应用的视觉体验与特色。
87 11
|
6月前
|
Web App开发 Android开发
FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo
实时数据传输在互联网中至关重要,不仅支持即时通讯如QQ、微信的文字与图片传输,还包括音视频通信。一对一通信常采用WebRTC技术,如《Android Studio开发实战》中的App集成示例;而一对多的在线直播则需部署独立的流媒体服务器,使用如SRT等协议。SRT因其优越的直播质量正逐渐成为主流。本文档概述了SRT协议的使用,包括通过OBS Studio和SRT Streamer进行SRT直播推流的方法,并展示了推流与拉流的成功实例。更多细节参见《FFmpeg开发实战》一书。
99 1
FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo
|
6月前
|
安全 测试技术 调度
iOS开发-多线程编程
【8月更文挑战第12天】在iOS开发中,属性的内存管理至关重要,直接影响应用性能与稳定性。主要策略包括:`strong`(强引用),保持对象不被释放;`weak`(弱引用),不保持对象,有助于避免循环引用;`assign`(赋值),适用于基本数据类型及非指针对象类型;`copy`(复制),复制对象而非引用,确保不变性。内存管理基于引用计数,利用自动引用计数(ARC)自动管理对象生命周期。此外,需注意避免循环引用,特别是在block中。最佳实践包括理解各策略、避免不必要的强引用、及时释放不再使用的对象、注意block中的内存管理,并使用工具进行内存分析。正确管理内存能显著提升应用质量。
|
6月前
|
JSON 搜索推荐 定位技术
打造个性化天气应用:iOS开发实战
【8月更文挑战第31天】在这篇文章中,我们将一起探索如何从零开始构建一个iOS天气应用。通过简单易懂的步骤,你将学习到如何使用Swift编程语言和苹果的开发工具Xcode来实现这个目标。我们会涉及到用户界面设计、网络编程以及数据解析等关键技能,确保你能够顺利地完成这个项目。无论你是初学者还是有一定经验的开发者,这篇文章都会带给你新的启发和收获。
|
1月前
|
iOS开发 开发者
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
141 67
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
|
3月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。

热门文章

最新文章

  • 1
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
  • 2
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    微信小程序 app.json 配置文件解析与应用
  • 4
    【Azure App Service】基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?
  • 5
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 6
    【Azure Function】Function App出现System.IO.FileNotFoundException异常
  • 7
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力
  • 8
    【Azure Logic App】使用MySQL 新增行触发器遇见错误 :“Unknown column 'created_at' in 'order clause'”
  • 9
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 10
    阿里云APP备案流程图以及备案所需材料整理,跟着教程一步步操作