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


相关文章
|
1月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
88 3
|
1月前
|
iOS开发 开发者
一键制作 iOS 上架 App Store 描述文件教程
一键制作 iOS 上架 App Store 描述文件教程
|
1月前
uni-app 185iOS端兼容处理
uni-app 185iOS端兼容处理
36 1
|
2月前
|
iOS开发 开发者
苹果iOS App Store上架操作流程详解:从开发者账号到应用发布
很多开发者在开发完iOS APP、进行内测后,下一步就面临上架App Store,不过也有很多同学对APP上架App Store的流程不太了解,下面我们来说一下iOS APP上架App Store的具体流程,如有未涉及到的部分,大家可以及时咨询,共同探讨。
|
2月前
|
安全 数据安全/隐私保护 iOS开发
iOS App 上架流程图文教学
在上架App 之前必须先准备好开发者帐号,但申请开发者帐号因法兰克早在之前已经申请好了,故就跳过此步骤,直接从产生凭证到上传App开始讲起。首先,要将自己辛苦写好的App 送审的话,则要依序做完下列几件事情即可。
|
1月前
|
Android开发 iOS开发 开发者
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
97 0
|
1月前
|
开发者 iOS开发
iOS App上架新规解析:如何进行App备案
iOS App上架新规解析:如何进行App备案
144 0
|
1月前
|
iOS开发 开发者
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
|
1月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十六):【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
正如优秀的软件设计一样,uni-app把一些移动端常用的功能做成了独立的服务或者插件,我们在使用的时候只需要选择使用即可。但是在使用这些服务或者插件时一定要区分其提供的各种服务和插件的使用场景,例如其提供的【uni-starter快速开发项目模版】几乎集成了移动端所需的所有基础功能,使用非常方便,但是其许可协议只允许对接其uniCloud的JS开发服务端,不允许对接自己的php、java等其他后台系统。
145 2
|
2月前
|
iOS开发 开发者
iOS App 上架指南及关键建议
上架App Store是将iOS应用提交申请并上线的过程,旨在让应用在App Store上展示,吸引用户并获取流量。本文将介绍iOS上架的整体流程,并提供一些建议和注意事项。