热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

frame越过另一个frame_SwiftUI从零开始做一个少数派客户端

在学习Swift2.0正式来临之前,我决心先体验一下使用SwiftUI写个小软件。本文基于目前的SwiftUI开发并没有使用任何2.0的新特性。熟悉基本操作首先多出来
在学习Swift 2.0 正式来临之前,我决心先体验一下使用 SwiftUI 写个小软件。本文基于目前的 SwiftUI 开发并没有使用任何2.0的新特性。

熟悉基本操作

4816f82dfed02c711fa2720c6ebbb5be.png

首先多出来这个界面叫做 Canvas 不小心关掉的话可以在 Editor > Canvas 打开

左下角的 可以在切换文件固定这个界面,很方便的功能

右下角是很普通的缩放功能 右侧有两个按钮▶️可以让 preview 运行起来, 可以让 preview 之间在设备上运行

效果图

3af7ca9dce1cf6ec0b5acdec0e00c42c.png

App 整体上就是一个文章列表,每个文章点进去就是一个 web view,所以组件就三个:

  • List 文章列表
  • Cell 列表元素显示-图片,标题和副标题
  • WebView 网页-文章内容

数据模型

根据 API 接口 https://sspai.com/api/v1/article/index/page/get 返回的数据创建数据模型

struct NetworkResponse : Codable {let msg: Stringlet error: Intlet data: T
}
struct ItemBean: Codable, Identifiable {let id: Intlet title: Stringlet summary: Stringlet banner: String//... more
}

List组件需要 item 满足 Identifiable 协议

List

创建文件ItemList.swift

struct ItemList: View {@State var items: [ItemBean] = []var body: some View {List(0 ...self, from: data).data else {// Errorreturn}DispatchQueue.main.async {self.items = items}}.resume()}
}

@State修饰符可以关联View的状态,当item变化会重新创建视图 self.items = items这行代码会刷新界面需要放到DispatchQueue.main

Cell

Cell就很普通,后面在加图片。

struct ItemCell: View {let item: ItemBeanvar body: some View {VStack {Text("https://cdn.sspai.com/" + item.banner)Text(item.title).font(.headline)Spacer().frame(height: 8)Text(item.summary).font(.subheadline).foregroundColor(Color.secondary)}}
}

WebView

SwiftUI的组件中是没有WebView的,但是提供了UIViewRepresentable来使用UIKit中的组件,只需要实现协议即可。

struct WebView: UIViewRepresentable {let urlString: Stringfunc makeUIView(context: Context) -> WKWebView {guard let url = URL(string: self.urlString) else {return WKWebView()}let requeset = URLRequest(url: url)let wk = WKWebView()wk.isOpaque = falsewk.load(requeset)return wk}func updateUIView(_ uiView: WKWebView, context: Context) {}
}

导航

把列表放到 NavigationView 中,Cell 放到 NavigationLink 中。

如果要改导航栏,在NavigationView里面的view改 直接使用NavigationLink会有一个箭头,可以放到ZStack中 导航出来的有SafeArea,如果想要全屏显示可以用edgesIgnoringSafeArea(Edge.Set.all)

NavigationView {List(0 ..}

网络图片

SwiftUI 目前还没有支持简单网络图片加载,不过有特别好用的第三方库,也可以自己写一个简单的用。不过还是建议使用成熟的第三方解决方案。

struct NetWorkImage: View {init(url: URL) {self.imageLoader = Loader(url)}@ObservedObject private var imageLoader: Loadervar image: UIImage? {imageLoader.data.flatMap(UIImage.init)}var body: some View {VStack {if image != nil {Image(uiImage: image!).resizable()} else {EmptyView()}}}}final class Loader: ObservableObject {var task: URLSessionDataTask!@Published var data: Data? = nilinit(_ url: URL) {task = URLSession.shared.dataTask(with: url, completionHandler: { data, _, _ inDispatchQueue.main.async {self.data = data}})task.resume()}deinit {task.cancel()}
}

改造之前的 Cell,让它显示图片

struct ItemCell: View {let item: ItemBeanvar body: some View {VStack {GeometryReader { geometry inNetWorkImage(url:URL(string: "https://cdn.sspai.com/(self.item.banner)")!).scaledToFill().frame(width: geometry.size.width, height: geometry.size.width/2).clipShape(RoundedRectangle(cornerRadius: 16))}.aspectRatio(2, contentMode: .fit).clipped()Text(item.title).font(.headline)Spacer().frame(height: 8)Text(item.summary).font(.subheadline).foregroundColor(Color.secondary)}}
}

刷新 加载更多

下拉刷新暂时没有比较简单的方案,我就直接导航上加一个刷新按钮。 加载更多就比较简单,给 Cell 加onAppear {self.fetchMoreItemsIfNeed(current: index)}根据index判断是否加载更多。ItemList最终代码就设这样的:

struct ItemList: View {&#64;State var items: [ItemBean] &#61; []var body: some View {NavigationView {List(0 ...self, from: data).data else {// Errorreturn}DispatchQueue.main.async {self.items &#61; items}}.resume()}func fetchMoreItemsIfNeed(current: Int) {guard current &#61;&#61; self.items.count - 1 else {return}let url &#61; URL(string: "https://sspai.com/api/v1/article/index/page/get?limit&#61;10&offset&#61;(items.count)")!URLSession.shared.dataTask(with: url) { (data, response, error) inDispatchQueue.main.async {guard let data &#61; data else {// Errorreturn}guard let items &#61; try? JSONDecoder().decode(NetworkResponse<[ItemBean]>.self, from: data).data else {// Errorreturn}self.items.append(contentsOf: items)}}.resume()}
}

总结

这是我第一个使用 SwiftUI 完成的 App&#xff0c;支持 iOS 和 Mac。熟悉 Flutter 的我用 SwiftUI 刚开始的感到很难受&#xff0c;Apple 的工具链还非常不完善&#xff0c;不过熟悉的之后会好一些&#xff0c;不过还是希望下个版本有所改进吧。

  • 缺点
    • 在布局的时候不要妄图让Xcode告诉你改怎么写&#xff0c;代码提示真的真的真的会让人崩溃。
    • 调试的时候要不要太在意错误提示的信息&#xff0c;真的没用。
    • 文档很简陋&#xff0c;也没有示例代码&#xff0c;全靠 Google
  • 优点
    • 调试界面不用运行整个项目&#xff0c;改了界面也能马上生效&#xff0c;我觉得比 Flutter 还好用
    • SwiftUI 代码很直观
Github​github.com


推荐阅读
  • 本文将介绍如何在混合开发(Hybrid)应用中实现Native与HTML5的交互,包括基本概念、学习目标以及具体的实现步骤。 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 第六章:枚举类型与switch结构的应用分析
    第六章深入探讨了枚举类型与 `switch` 结构在编程中的应用。枚举类型(`enum`)是一种将一组相关常量组织在一起的数据类型,广泛存在于多种编程语言中。例如,在 Cocoa 框架中,处理文本对齐时常用 `NSTextAlignment` 枚举来表示不同的对齐方式。通过结合 `switch` 结构,可以更清晰、高效地实现基于枚举值的逻辑分支,提高代码的可读性和维护性。 ... [详细]
  • 在Kohana 3框架中,实现最优的即时消息显示方法是许多开发者关注的问题。本文将探讨如何高效、优雅地展示flash消息,包括最佳实践和技术细节,以提升用户体验和代码可维护性。 ... [详细]
  • 本文详细介绍了 Spark 中的弹性分布式数据集(RDD)及其常见的操作方法,包括 union、intersection、cartesian、subtract、join、cogroup 等转换操作,以及 count、collect、reduce、take、foreach、first、saveAsTextFile 等行动操作。 ... [详细]
  • 本文详细介绍了 com.apollographql.apollo.api.internal.Optional 类中的 orNull() 方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 一个建表一个执行crud操作建表代码importandroid.content.Context;importandroid.database.sqlite.SQLiteDat ... [详细]
  • C#实现文件的压缩与解压
    2019独角兽企业重金招聘Python工程师标准一、准备工作1、下载ICSharpCode.SharpZipLib.dll文件2、项目中引用这个dll二、文件压缩与解压共用类 ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • This feature automatically validates new regions using the AWS SDK, ensuring compatibility and accuracy. ... [详细]
  • 本文汇集了我在网络上搜集以及在实际面试中遇到的前端开发面试题目,并附有详细解答。无论是初学者还是有一定经验的开发者,都应深入理解这些问题背后的原理,通过系统学习和透彻研究,逐步形成自己的知识体系和技术框架。 ... [详细]
  • 本文详细介绍了使用 Python 进行 MySQL 和 Redis 数据库操作的实战技巧。首先,针对 MySQL 数据库,通过 `pymysql` 模块展示了如何连接和操作数据库,包括建立连接、执行查询和更新等常见操作。接着,文章深入探讨了 Redis 的基本命令和高级功能,如键值存储、列表操作和事务处理。此外,还提供了多个实际案例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 在 Swift 中,初始化器的参数名称使用 "with" 前缀是一种常见的规范,但需要注意的是,对于第一个参数,编译器默认会省略外部参数名。因此,直接在第一个参数前使用 "with" 会导致编译错误。本文深入探讨了这一规范的最佳实践,并提供了避免此类错误的具体方法,帮助开发者更好地理解和应用 Swift 的初始化器设计原则。 ... [详细]
author-avatar
CHANBunCHAI
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有