使您现有的业务解决方案适应SwiftUI。第1部分

祝大家有美好的一天。我叫安娜·扎尔科娃(Anna Zharkova),我是Usetech

关于SwiftUI技术的领先移动开发者,有关该技术,苹果公司于去年WWDC 2019上宣布了很多说法。原则上,已经有足够的材料来介绍其功能,其内幕内容以及如何将其用于快速美观的UI。



我为您提供了有关如何在现实生活和实际应用中而不是在鳄梨三明治构造函数中使用此框架的简短文章。为了使每件事变得严肃和成熟,我们将研究如何使SwiftUI应用程序符合简洁架构和简洁代码的原则。

但是,让我们从基础开始。这一部分只是介绍和基本信息。因此,如果您已经熟悉这些SwiftUI功能,请继续以下部分:
第2部分(如何在UIKit下使用现成的库)
第3部分(此处与体系结构有关)和
第4部分(此处与导航有关)

如果您还不认识,请继续学习几分钟)

在新框架中声明式开发的主要功能是与直接使用UIViewController,UIView以及使用实现View协议的结构代替直接使用有所不同。视觉部分的所有组件也使用声明性语法进行描述,并且位于每个View的主体属性内。设置,样式化和组件自定义,屏幕视图之间的导航也使用声明性语法进行设置。

例如,此代码通过单击一个带有单独新闻视图的屏幕来描述新闻列表的视图:

struct NewsListView: View{
    @State var data: [NewsItemMock]
    
    var body: some View {
        NavigationView{
        List(data) { item in
            NavigationLink(destination:NewsItemView(item:item)) {
            NewsItemRow(data: item)
            }
        }
    }
}

SwiftUI使用ViewBuilder,这是一个基于Functional Builder的声明性界面设计器。这种机制出现在Swift 5.1中,它允许您将元素分组到闭包块内的某个数组中,例如父对象。幻灯片中提供了一个使用ViewBuilder的示例。我们只需要按照需要的顺序放置View控件,例如,在垂直或水平Stack内,而不使用addSubview,并且在编译SwiftUI本身时会将元素添加和分组到更复杂的父容器中。

这是代码:


          VStack {
            HStack {
                VStack(alignment: .leading,spacing: 10) {
                    HeaderText(text: data.title ?? "")
                    SubheaderText(text: data.description ?? "")
                    SmallText(text: data.publishedAt?
                                   .formatToString("dd.MM.yyyy") ?? "")
                }
               ThumbImage(withURL: data.urlToImage ?? "")
             }

转换为包含3个文本字段和一个图像的列表项:


尽管SwiftUI否认UIViewController的概念,但应用程序的入口点是UIHostingController,将所显示的View传递并嵌入其中。也就是说,实际上,新技术是UIKit的附加组件:


@available(iOS 13.0, tvOS 13.0, *)
open class UIHostingController<Content> : UIViewController where Content : View {

    public var rootView: Content

    public init(rootView: Content)


顺便说一下,所有SwiftUI控件都是UIKit控件的声明性类似物。

例如,VStack,HStack分别是通常的垂直和水平UIStackView的类似物。列表是UITableView,文本是UILabel,按钮是UIButton,图像是UIImage,等等。

使用可用的修饰符可以声明性地连接和配置控件。元素在具有一些预定义属性的UIStackView类似物内分组。

除了更改描述可视部分的方式之外,数据流控制和UI对其的反应机制也在更改。Swift UI是一个非事件依赖的框架那些。其中的视图是某些状态的函数而不是事件序列的结果。用户执行的操作不会直接更改UI,也无法直接更改此或该View,添加或删除控件。首先,通过一个或另一个Property包装器(property wrappers)连接到View的属性或状态变量change



主要使用的属性包装器有:

1。 -用于局部变量。


struct NewsItemRow: View {
    @State var title: String
    @State var  description: String
    @State var dateFormatted: String 
    @State var imageUrl: String 
    
    var body: some View {
        VStack {
            HStack {
                VStack(alignment: .leading,spacing: 10) {
                    HeaderText(text: title)
                    SubheaderText(text: description)
                    SmallText(text: dateFormatted)
                }
              ThumbImage(withURL: imageUrl)
            }
         }
     }

2. @Binding-弱的类似物,在将引用传递给值时使用。

当一个以上的View依赖于任何属性时,我们将使用它。例如,如果我们要将值从第二级的视图传递到原始视图。


struct FirstView: View {
    @State var isPresented: Bool = true
    
    var body: some View {
        NavigationView {
            NavigationLink(destination:
            SecondView(isPresented: self.$isPresented)) {
                Text("Some")
            }
        }
    }
}

struct SecondView: View {
    @Binding var isPresented: Bool
    
    var body: some View {
        Button("Dismiss") {
            self.$isPresented = false
        }
    }
}

3. @EnvironmentObject-在视图之间传输对象

4. @ObjectBinding,@ObservableObject-用于使用Combine框架工具跟踪模型属性中的更改。


class NewsItemModel: ObservableObject,IModel {
   @Published var title: String
   @Published var  description: String
   @Published var dateFormatted: String 
   @Published var imageUrl: String 
}

我们待会儿再谈他。

所以。如果要更改视图,则更改属性,即带有属性包装器之一的广告。然后,使用所有内部控件重建声明式视图。
当任何状态变量更改时,视图将整体重建。

考虑一个小例子。我们有一个屏幕,在导航栏中有一个按钮,用于将内容添加到收藏夹。为了使我们可以更改此按钮上的指标图像,我们将使用PropertyWrappers。例如,在这种情况下,创建一个局部变量并将其声明为


struct NewsItemView: View {
@State var isFavorite: Bool 
....

我们将属性值更改分配给按下按钮时发生的触发事件:

struct NewsItemView: View{
    @State var isFavorite: Bool 
   
    var body: some View {
    NavigationView {
    VStack {
        Text("Some content")
       }
    }
     .navigationBarItems(trailing: Button(action: {
            self.isFavorite = !self.isFavorite
        }){
            Image(self.isFavorite ? "favorite" : "unfavorite")
           .frame(width: 20, height: 20, alignment: .topTrailing)
        })
   }
        

因此,我们的视图将发生变化:



原则上,这是您需要了解有关SwiftUI入门的所有基本知识。

但这足以工作吗?

通过简单的控件创建简单的UI,而无需完全绑定到Xib和情节提要。

还有更多,没有。

首先,并非所有控件在SwiftUI中都有类似物。这既适用于标准UIKit UISearchView,UICollectionView,也适用于第三方库中的哪些元素。

其次,没有(或几乎没有,也许有人正在这样做)用于Data Flow SwiftUI的第三方解决方案。

因此,您必须将现有解决方案改编为标准iOS应用程序。

请点击链接。

All Articles