简介

SwiftUIApple推出的现代界面结构,旨在简化界面开发和布局,并提供强大的响应式编程动画支撑。与UIKit的一个最明显的差异便是:SwiftUI是一个纯coding式的结构,摒弃了UIkit的结合图形界面设计东西构建视图的功用

概念

下面会从SwiftUI的几个根底并且重要的知识概念出发,从而能够大致理清并了解SwiftUI 结构的大致组成结构,到达在运用SwiftUI这个结构时能够愈加理性的目的

  • UI 控件
    • 常用控件
    • 控件款式
      • 链式调用
      • view modifier
    • 动画
  • 生命周期
    • 视图
    • 运用程序
  • 适配

UI 控件

SwiftUI中,有许多常用的UI 控件可用于构建运用程序的用户界面,一起还能对这些UI 控件的款式进行调整,设计出想要的页面作用

常用控件

  • Text:用于显现文本内容,支撑自定义款式、字体和颜色
  • Label:用于显现带有图标的文本标签,一般用于表示标签或标题
  • Button:创立一个可点击的按钮,用于执行操作或导航到其他视图
  • LinkButton:类似于 Button,但用于打开外部链接或导航到其他运用程序
  • TextField:用于接受用户的文本输入
  • Image:用于显现图画,支撑本地图画和网络图画
  • NavigationView:用于创立导航界面的容器
  • NavigationLink:创立一个可点击的导航链接
  • ScrollView:用于翻滚内容,以显现更多的信息
  • List:用于显现可翻滚的列表,支撑分组和行操作
  • Form:类似于 List,但用于创立表单布局,自动习惯键盘弹出
  • Alert:用于显现警报音讯和操作
  • ActionSheet:用于显现一个带有多个操作选项的弹出菜单
  • VStack:垂直仓库布局,用于按垂直方向摆放视图
  • HStack:水平仓库布局,用于按水平方向摆放视图
提示
  • Section也是一个 UI 控件,可是不能独自运用,而是用于构建列表表格布局组件Section一般用于将列表表格中的内容分组显现
  • VStackHStack是用于页面布局的,常常频频运用

控件款式

SwiftUI中构建用户界面时,能够运用链式调用封装 View Modifier来进行款式调整。这些方法使得在不同视图上运用类似的款式变得十分快捷,一起还能够增强代码的可读性和可维护性

1. 链式调用

SwiftUI中,能够通过链式调用在视图上运用多个修饰符,从而逐步构建视图的款式。每个修饰符调用都会返回一个新的视图,能够在其上持续运用其他修饰符

struct ProfileHeaderView: View {
    @State var lineWidth = CGFloat(4)
    @State var radius = CGFloat(7)
    var body: some View {
        Image(avatarUrl)
            .resizable()
            .clipShape(Circle())
      .overlay(Circle().stroke(Color.orange, lineWidth: lineWidth))
      .shadow(radius: radius)
      .animation(.default.repeatForever(), value: lineWidth)
      .animation(.default.repeatForever(), value: radius)
      .onAppear {
        lineWidth = 2
        radius = 4
      }
            .frame(width: 60, height: 60)
    }
}

上面这个比如是绘制一个包括外框且有动画的头像框,能够看到首要是运用Image这个控件来完结,外框、动画则都是对这个UI 控件的款式进行调整,选用链式调用内置的修饰符来完结

2. 封装 View Modifier

除了运用内置的修饰符外,您还能够创立自定义的View Modifier将常用的款式封装起来,以便在多个视图中重复运用,这使得你能够在代码中引进更高层次的笼统,使得代码更具可重用性可维护性

struct ProfileHeaderView: View {
    var body: some View {
        Image(avatarUrl)
            .resizable()
            .circle()
            .frame(width: 60, height: 60)
    }
}
struct CircleModifier: ViewModifier {
  @State var lineWidth = CGFloat(4)
  @State var radius = CGFloat(7)
  func body(content: Content) -> some View {
    content
      .clipShape(Circle())
      .overlay(Circle().stroke(Color.orange, lineWidth: lineWidth))
      .shadow(radius: radius)
      .animation(.default.repeatForever(), value: lineWidth)
      .animation(.default.repeatForever(), value: radius)
      .onAppear {
        lineWidth = 2
        radius = 4
      }
  }
}
extension Image {
  func circle() -> some View {
    modifier(CircleModifier())
  }
}

上面这个比如则是在链式调用的根底上进行了封装,把多个款式封装成一个款式行为,归于更高层次的款式运用。虽然完成的作用是相同的,可是当多处需要运用到上面的款式时,运用View Modifier封装的款式能让你少写更多相同款式代码

动画

SwiftUI中,能够运用内置的动画功用UI 控件添加动画作用,以增强用户体验。动画能够运用于特点的更改,从而使控件的状况转换愈加平滑和引人注目

在上面的比如中有运用到动画修饰符,能够看到需要给动画定义一个触发时机

运用动画有两种方法

  • 动画修饰符.animation
  • 动画APIwithAnimation

下面就运用之前的比如对比演示一下两者运用上的一些差异:

@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
// .animation
Image(avatarUrl)
    .animation(.default.repeatForever(), value: lineWidth)
    .animation(.default.repeatForever(), value: radius)
    .onAppear {
        lineWidth = 2
        radius = 4
    }
// withAnimation
Image(avatarUrl)
    .onAppear {
        withAnimation(.default.repeatForever()) {
            lineWidth = 2
            radius = 4
        }
    }

生命周期

SwiftUI的生命周期与UIkit不同挺大的,首先便是没有UIkit那么详细的生命周期函数,然后便是SwiftUI的生命周期分为视图运用程序两种

  • 视图:生命周期函数被缩减为只剩onAppearonDisappear两个
  • 运用程序:生命周期与ScenePhase密切相关
    • .active:运用程序处于活动状况,即在前台运转,用户能够与运用程序进行交互
    • .inactive:运用程序处于非活动状况,即在前台运转,但用户不能与运用程序交互
    • .background:运用程序处于后台运转状况

SwiftUI运用程序生命周期的运用案例:

struct MySwiftUIApp: App {
    @Environment(\.scenePhase) private var scenePhase: ScenePhase
    var body: some Scene { 
        WindowGroup { 
            ContentView() 
        }
        .onChange(of: scenePhase) { newScenePhase in
            layoutWithScenePhase(newScenePhase: newScenePhase)
        }
        private func layoutWithScenePhase(newScenePhase: ScenePhase) {
            switch newScenePhase{
            case .active:
                // code
            case .inactive:
                // code
            case .background: 
                // code
            @unknown default: break
            }
        }
    }
}

适配

SwiftUI中,适配涉及保证运用程序在不同设备之间(如iPhoneiPad)以及不同屏幕尺度分辨率之间都能正常显现

下面列举两个SwiftUI针对不同设备类型的适配方案:

  • Size Classes(尺度类别)
  • UIDevice.current.userInterfaceIdiom

Size Classes

SwiftUI运用尺度类别来表示设备的巨细方向,如:compactregular。在视图中运用.horizontalSizeClass.verticalSizeClass来检测设备的尺度类别,并根据需要运用不同的布局和款式

struct ContentView: View {
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    @Environment(\.verticalSizeClass) var verticalSizeClass 
    var body: some View { 
        VStack(alignment: .leading) { 
            if horizontalSizeClass == .compact && verticalSizeClass == .regular { 
                layoutWithUserInterfaceIdiom()
            } else { 
                HStack {
                    layoutWithUserInterfaceIdiom()
                }
            } 
        } 
    } 
}

UIDevice.current.userInterfaceIdiom

UIDevice.current.userInterfaceIdiomUIKit中用于判断设备类型的特点,能够在iPhoneiPad之间进行适配,但如果需要在SwiftUI中运用UIKit特点来判断设备类型,也是能够的

struct ProfileHeaderView: View {
    @State var userInterfaceIdiom = UIDevice.current.userInterfaceIdiom
    var body: some View {
        VStack(alignment: .leading) {   
            if userInterfaceIdiom == .phone {
                HStack {
                    layoutWithUserInterfaceIdiom()
                }
            } else {
                layoutWithUserInterfaceIdiom()
            }
        }
    }
}

小结

关于SwiftUI的学习,与UIkit的学习路线大致上是类似的,但由于SwiftUI是一种全新的声明式结构,运用方法和一些概念可能会有所不同

关于SwiftUI 结构的运用,本文首要叙述了其通用 UI控件款式动画生命周期以及适配问题等,在后续的文章中会陆续对SwiftUI中的特点包装器缓存以及网络请求进行谈论及总结

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。