热门标签 | 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


推荐阅读
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社区 版权所有