开发OS X 图形应用界面时有三种实现方式:XIB、Storyboard、SwiftUI。Storyboard基于XIB做了优化,XIB基本被放弃了,而SwiftUI是苹果公司后来开发的一套编程语言,用来平替Objective-C。虽然现在最新版本的Swift 6 还是有些不完善的地方,但可以看到此为未来的主流。

  • 本系列课主要讲下SwiftUI方面的知识,不会过多涉及Swift基础语言,Swift可以查看笔者的另一个专题。本节做为第一节内容,主要课下应用构建的基础知识。
  • 笔者的开发环境为: Xcode Version 16.1 (16B40)、Swift 5,需要注意不同版本的Xcode其界面会有稍许差异,不同版本的Swift语言的API也会有一定的差异。

创建工程

所有的示例笔者会统一使用IOS APP做为工程类型(少量会采用OS X类型),无论是OS还是IOS这对学习SwiftUI没有任何影响。

创建工程

在这里插入图片描述
一路Next,最后工程结构如下:
在这里插入图片描述

  • Preview Content:用于存放预览内容,开发者可以利用这些预览内容来快速查看和验证设计的界面在不同设备和屏幕尺寸上的表现,从而提高开发效率和界面质量;
  • .entitlements:相当于原来的info.plist文件,用于配置工程的一些设置,这个文件一般不需要手动编辑,更新工程设计时会自动更新;
  • Assets.xcassets:资源文件,主要用于存放图标、图片、颜色等资源;
  • XxApp.swift:工程启动入口函数,相当于main();
  • ContentView.swift:SwiftUI 界面设计源码,在正式程序中可能会有多个这样的UI界面源码文件,工程默认创建的这个视图文件会被XxApp.swift调用。

工程源码

  • 启动文件
import SwiftUI

@main  // 注意此标的使用
struct _1_base1App: App { //实现App协议
    var body: some Scene { //图控制器或应用入口点
        WindowGroup {
            ContentView() //调用UI实现类,可以更改
        }
    }
}
  • Swift UI 视图,下面代码中的组件的代码写法需要注意一下,多个组件一般用换行隔离,而不是逗号或分号。
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack { //布局
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}

 //这行是此View展示时的初始化方法,只用于预览用,没实际用处
#Preview {
    ContentView()
}

工程运行

在运行前最基本的有几个设置需要确认一下:

  • targets:同一工程可设置多个运行目标,可在项目设置的General面板中设置;
  • swift版本:可在building settings面板中设置;
    在这里插入图片描述

新建界面

如果要创建新的UI,可选择File- New- File from template,选择SwiftUI
在这里插入图片描述
默认代码如下:

import SwiftUI

struct SwiftUIView: View {
    var body: some View {
        Text("Hello, World!")
    }
}

#Preview {
    SwiftUIView()
}

Doc帮助文档

  • 中文文档: https://gitee.com/guangjie2021/SwiftUICn
  • 苹果官方:https://developer.apple.com/documentation

添加组件

这里只介绍几个了解一下,后面还有专门的章节讲解,详细的可以参考上述文档中的内容。

Text 文字

基础代码如下,下面代码中有一些是.gray的写法,其是为了简便编程,把位于SwiftUICore中对象的一些名称在调用时省略了,Text相当于Label用于显示描述方案用。

import SwiftUI

struct SwiftUIText: View {
    var body: some View {
        VStack{
            Text("这是一个swiftui实现的文本label,可以设置一些属性")
                .font(.custom("slideyouran-Regular", size: 23))
                .foregroundColor(.gray)
                .lineLimit(2)
                .multilineTextAlignment(.center)
                .padding()
            
            Text("以下是一些详情信息")
                .font(.system(size: 23))
        }
        .padding()
    }
    
}

#Preview {
    SwiftUIText()
}
  • 自定义字体,在上述代码中有一行.font(.custom("slideyouran-Regular", size: 23))代码,这种是一种自定义字体的写法,集成自定义字体的方法是:
  1. 拷贝.ttf字体文件到工程中;
  2. 配置工程info信息;
  3. 采用.custom()调用引用;

工程info配置方法如下图所示,其中item 0 后面的值为字体的名称,这个名称可能会和文件名不一样,需要在系统中安装一下字体再确定其名称:
在这里插入图片描述
注意查看字体名称如何查看
在这里插入图片描述

Image 图片

图片有三种实现方式:

加载资源库图标

就是Assets库中的图片,在这个视图中可以添加文件夹等信息,但在使用时不需要关注其路径问题,但也意味着名称要唯一。

Image("DemoImg")
    .resizable()
    .scaledToFit()
    .frame(width: 64)
    .cornerRadius(12)

加载系统图标

苹果官方开发一个名为SF Symbols图标库的软件,这个软件主要用于查找系统图标名称,同时还能自动生成一些代码,供开发时何用。
在这里插入图片描述
这些图标相当于文字图标,可以使用内置函数设置颜色,线条等样式。

Image(systemName: "square.and.arrow.up.circle")
    .font(.system(size: 52))
    .symbolEffect(.bounce)
    .padding(12)

加载网络图片

就是从互联网上下载图片,但除了打开工程的client设置开关外,还需要注意URL只能是https开头的。

            // 这是一种闭包写法:
            // image in:这是闭包的开始,image 是闭包的参数,代表加载的图像
            AsyncImage(url: URL(string: imageUrl)) { image in
                        image  // 这个闭包在图像加载完成后被调用
                            .resizable()
                            .scaledToFit()
                            .frame(width: 280)
                            .cornerRadius(16)
                    } placeholder: {
//                        Text("图片加载中")
//                            .font(.system(size: 24))
//                            .foregroundColor(.gray)
//                            .padding()
//                            .frame(width: 280,height: 160)
//                            .cornerRadius(16)
                        ProgressView()
                    }

在这里插入图片描述

自定义组件

SwiftUI的自定义组件比较简单,可以先了解下简单实现,后面章节再详细讲解。

自定义组件

比如如下代码,定义了一个自定义的TextDemo组件。可以封装成比较复杂的套件,这和OS X桌面应用不一样,桌面的控件会比较复杂,而IOS所有自定义组件基本全继承View即可。

import SwiftUI

// MARK: - 文字组件
struct TextDemo: View { 
   //组件参数
    var text: String
    var textSize: CGFloat
    var textColor: Color

   //组件样式
    var body: some View {
        Text(text)
            .font(.system(size: textSize))
            .foregroundColor(textColor)
    }
}

自定义组件调用

自定义组件调用

import SwiftUI

struct SloganTextView: View {
    var body: some View {
        VStack(spacing: 10) {
            TextDemo(text: "你好,世界。", textSize: 23, textColor: .black)
            TextDemo(text: "愿日子如熹光,愿你能幸福~", textSize: 17, textColor: .gray)
        }
    }
}

预览效果如下:
在这里插入图片描述

视图布局

SwiftUI中内置了三种纯布局组件:VStack、HStack、ZStack,示例代码写法,上述三种组件可做为一个容器使用(只布局不显示),后续还会讲其它的几种常用布局组件。

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("我是启动页")
        }
        .padding()
    }
}

主界面设计

实现一个底图+图标这样的简单设计。
在这里插入图片描述

import SwiftUI

struct StartUpUI: View {
    var body: some View {
            ZStack(alignment: .bottom) {
                // 背景图片
                Image("starup")
                    .resizable()
                    //.aspectRatio(contentMode: .fill)
                    .edgesIgnoringSafeArea(.all)
                VStack {
                    Spacer() // 占位空间
                    
                    // 应用图标和应用名称
                    HStack(alignment: .center, spacing: 20) {
                        // 应用图标
                        Image("DemoImg")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 60)
                            .cornerRadius(16)

                        // 应用名称
                        Text("世纪佳人")
                            .font(.system(size: 32))
                            .foregroundColor(.white)
                            .bold()
                    }
                }
            }
        }
}

#Preview {
    StartUpUI()
}

常用方法

组件设置

组件的样式很多的操作都需要以resizable()为前提,而且有些特殊的会有先后调用顺序。比较常用的组件样式设置方法如下:

  • resizable():设置组件是否可以改变尺寸;
  • aspectRatio():在resizable()打开后,指定调整尺寸时的横纵比和固定比;
  • edgesIgnoringSafeArea():屏幕安全区设置,安全区是指手机屏幕中除了摄像头那个位置;
  • frame(width: 60):设置组件大小;
  • cornerRadius(32):设置圆角大小;

位置设置

  • Spacer():占位符,它会把已显示的元素计算完大小后,然后用空白填充占据其它空间,比如下面的代码就会中间位置占满,上下各一行文本。
`VStack {
    Text("这是顶部的文本")
    Spacer() // 占据剩余空间,将下面的文本推到底部
    Text("这是底部的文本")
}`
  • .frame():设置VStack的框架大小,下面这种infinity是一种自适应参数方式,非固定大小,建议用这种方式设置。
VStack {
    ......
}
.frame(maxWidth: .infinity, maxHeight: .infinity) // 设置VStack的框架大小
  • padding() 修饰符可以接受不同的参数来指定内边距的大小,默认为5px
Text("Hello, SwiftUI!")
    .padding(10.0) // 在文本视图周围添加10点的内边距

Text("Hello, SwiftUI!")
    .padding(.init(top: 10, leading: 20, bottom: 15, trailing: 25)) // 设置上、左(leading)、下、右(trailing)内边距

Text("Hello, SwiftUI!")
    .padding(.medium) // 使用中等大小的内边距

按钮与手势

SwiftUI的按钮实现有点特殊,它由两部分组成:事件+样式。其中事件只有点击事件,这样样式可以根据需要自定义,格式如下:

Button(action: {
    print("Tap") //事件
}) {
   Text("I'm a Button") //样式
}

Action 按钮点击事件

在这里插入图片描述

struct TextButton: View {
    var body: some View {
        Button(action: { //事件
            print("aaa")
        }) {
            Text("立即使用")  //样式
                .font(.system(size: 17))
                .foregroundColor(.white)
                .padding()
                .frame(width: 180)
                .background(
                    LinearGradient(gradient: Gradient(colors: [Color.blue, Color.green]), startPoint: .leading, endPoint: .trailing))
                .cornerRadius(16)
        }
    }
}

上述的样式部分也可以换成图标,如下面代码:

struct ImageBtnView: View {
    var body: some View {
        Button(action: {
            // 点击后的操作
        }) {
            Image("WoodenFish")
                .resizable()
                .scaledToFit()
                .frame(width: 160)
        }
    }
}

Gesture 手势点击事件

手势事件和按钮的区别在于:按钮是个组件,而手势是一种事件可以给任何组件添加点击事件,功能是一样的但用法不一样。
在这里插入图片描述
给组件添加onTapGesture()手势事件,下面代码中用到了@State,其为一种当前视图数据状态缓存技术,一种MVVM响应式编程实现(前端像React, Vue等框架基本全采用了这种模式实现),简单来讲就是采用观察者模式实现的数据和视图联动。

struct SwiftUIButton: View {
    @State var finNumber: Int = 1

    var body: some View {
        // 布局容器
        VStack(spacing: 32) {
            // 文字内容
            Text("功德+" + String(finNumber))
                .font(.system(size: 20))
                .foregroundColor(.black)

            // 图片按钮
            Image("WoodenFish")
                .resizable()
                .scaledToFit()
                .frame(width: 160)
                // 点击操作
                .onTapGesture {
                    finNumber += 1
                }
        }
    }
}

本节只是一个入门教程,后面还有很多高级的主题,可以循序汽渐进的来,SwiftUI的基础内容不是太多。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐