实战编程·使用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


相关文章
|
25天前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
118 66
|
1天前
|
安全 数据安全/隐私保护 Android开发
【05】2025年1月首发完整版-篇幅较长-苹果app如何上架到app store完整流程·不借助第三方上架工具的情况下无需花钱但需仔细学习-优雅草央千澈详解关于APP签名以及分发-们最关心的一篇来了-IOS上架app
【05】2025年1月首发完整版-篇幅较长-苹果app如何上架到app store完整流程·不借助第三方上架工具的情况下无需花钱但需仔细学习-优雅草央千澈详解关于APP签名以及分发-们最关心的一篇来了-IOS上架app
100 75
|
2月前
|
人工智能 自然语言处理 前端开发
用通义灵码,从 0 开始打造一个完整APP,无需编程经验就可以完成
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。本教程完全免费,而且为大家准备了 100 个降噪蓝牙耳机,送给前 100 个完成的粉丝。获奖的方式非常简单,只要你跟着教程完成第一课的内容就能获得。
11122 17
|
11天前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
|
2月前
|
传感器 iOS开发 UED
探索iOS生态系统:从App Store优化到用户体验提升
本文旨在深入探讨iOS生态系统的多个方面,特别是如何通过App Store优化(ASO)和改进用户体验来提升应用的市场表现。不同于常规摘要仅概述文章内容的方式,我们将直接进入主题,首先介绍ASO的重要性及其对开发者的意义;接着分析当前iOS平台上用户行为的变化趋势以及这些变化如何影响应用程序的设计思路;最后提出几点实用建议帮助开发者更好地适应市场环境,增强自身竞争力。
|
2月前
|
设计模式 Swift iOS开发
探索iOS开发:从基础到高级,打造你的第一款App
【10月更文挑战第40天】在这个数字时代,掌握移动应用开发已成为许多技术爱好者的梦想。本文将带你走进iOS开发的世界,从最基础的概念出发,逐步深入到高级功能实现,最终指导你完成自己的第一款App。无论你是编程新手还是有志于扩展技能的开发者,这篇文章都将为你提供一条清晰的学习路径。让我们一起开始这段旅程吧!
|
2月前
|
iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第39天】在苹果的生态系统中,SwiftUI框架以其声明式语法和易用性成为开发者的新宠。本文将深入SwiftUI的核心概念,通过实际案例展示如何利用这一框架快速构建用户界面,并探讨其对iOS应用开发流程的影响。
|
8月前
|
iOS开发 开发者
苹果iOS App Store上架操作流程详解:从开发者账号到应用发布
很多开发者在开发完iOS APP、进行内测后,下一步就面临上架App Store,不过也有很多同学对APP上架App Store的流程不太了解,下面我们来说一下iOS APP上架App Store的具体流程,如有未涉及到的部分,大家可以及时咨询,共同探讨。
|
8月前
|
安全 数据安全/隐私保护 iOS开发
iOS App 上架流程图文教学
在上架App 之前必须先准备好开发者帐号,但申请开发者帐号因法兰克早在之前已经申请好了,故就跳过此步骤,直接从产生凭证到上传App开始讲起。首先,要将自己辛苦写好的App 送审的话,则要依序做完下列几件事情即可。
|
8月前
|
安全 数据安全/隐私保护 开发者