38 SwiftUI

SwiftUI

image-20230312113352480.png
  • SwiftUI 是一种基于Swift的强大能力,简单创新的构建用户界面的方法,并且可以运行在苹果所有的平台上
image-20230312113624800.png

SwiftUI - 声明式语法

  • SwiftUI采用声明式语法,因为你可以简单声明你的用户界面
image-20230312113734752.png
  • Xcode11提供了强大的设计工具,可以通过简单的拖拽用SwiftUI生成用户界面
image-20230312114050160.png
  • 只需要描述一次的布局-为你的视图声明任何状态的内容和布局,一旦状态发生改变,SwiftUI会自动更新视图的渲染
  • 构建可复用的组件-将小型、独立视图组合到更大,更复杂的界面中。在任何为Apple平台所设计的应用之间,共享您的自定义视图
  • 精简动画-创建平滑的动画就像调用单个方法一样简单。SwiftUI会在必要时自动计算并过渡动画

SwiftUI设计工具使用指南

创建项目

image-20230312212430872.png

Stacks

image-20230312212509459.png

如何使用SwiftUI构建可复用的组件

地标页例子

image-20230312214019068.png

Image组件

image-20230312214151969.png
image-20230312214348729.png
image-20230312214400782.png
image-20230312214452467.png
struct ContentView: View {
    var body: some View {
        
        VStack {
            //设置安全距离
            MapView().edgesIgnoringSafeArea(.all)
                .frame(height: 300)
            
            CircleImage().offset(y: -130).padding(.bottom, -130)
            
            //左对齐
            VStack (alignment: .leading) {
                Text("圆明园").font(.title)
                HStack {
                    Text("皇家园林").font(.subheadline)
                    Spacer()
                    Text("北京").font(.subheadline)
                }
            }.padding()//边界留白
            
            Spacer()//留白
        }
        
        
    }
}

图片组件

struct CircleImage: View {
    var body: some View {
        //将图片剪切出一个圆
        Image("ymy").clipShape(Circle())
        //加一个边框线
        .overlay(Circle().stroke(Color.black, lineWidth: 4))
        .shadow(radius: 10)//阴影
    }
}

地图组件

import SwiftUI 
import MapKit

struct MapView; UIViewRepresentable {
    
    //创建地图组件
    func makeUIView(context: Context) -> MKMapView {
        return MKMapView(frame: .zero)
    }
    
    //对地图组件进行设置
    func updateUIView(_ uiView: MKMapView, context: Context) {
        //圆明园的经纬度
        let location = CLLocationCoordinate2D(latitude: 40.00491139888854, longitude: 116.2896180152893)
        //展示范围
        let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
        let region = MKCoordinateRegion(center: location, span: span)
        uiView.setRegion(region, animated: true)
    }
}

如何使用SwiftUI实现动画

SwiftUI - 动画

  • 在SwiftUI中,你可以将任意的改变过程封装进一个withAnimation块中。默认,SwiftUI会对这种改变采用fade in/out 的方式进行动画
struct AnimationView: View {
    
    //状态 当属性改变时, 会进行重写渲染
    @State private var showDetail = false
    
    var body: some View {
        Button(action: {
            withAnimation {
                self.showDetail = !self.showDetail
            }
        }) {
            Image(systemName: "chevron.right.circle")//使用了一张系统图片
                .imageScale(.large)//尺寸
                .rotationEffect(.degrees(showDetail ? 90 : 0))//旋转90度或0度
                .scaleEffect(showDeatil ? 1.5 : 1)//放大倍数
            .padding()
        }
    }
}

在这里更改显示入口

image-20230312224524873.png

深入理解SwiftUI:实现原理探秘

@propertyWrapper

  • 通过property Wrapper机制,对一些类似的属性的实现代码做同一封装
  • 通过@propertyWrapper可以移除掉一些重复或者类似的代码

@state

  • 通过@State SwiftUI 实现了值的绑定、动态查找和View的自动重现绘制
image-20230312225028447.png
image-20230312225141503.png
  • 课后题:查看源码,了解@Binding,@ObservedObject,@EnvironmentObject等装饰器的作用
extension UserDefaults {
    public enum Keys {
        static let hadShownUserGuide = "hadShownUserGuide"
    }
    
    var hadShownUserGuide: Bool {
        set {
            set(newValue, forKey: Keys.hadShownUserGuide)
        }
        
        get {
            bool(forKey: Keys.hadShownUserGuide)
        }
    }
}

struct PropertyWrapperView: View {
    @State private var showText = UserDefaults.standard.hasShownUserGuide ? "已经展示" : "没有展示过"
    
    var body: some View {
        Button(action: {
            if (!UserDefaults.standard.hasShownUserGuide) {
                UserDefaults.standard.hasShownUserGuide = true
                self.showText = "已经展示"
            }
        }) {
            Text(self.showText)
        }
    }
}
  • 使用propertyWrapper进行统一扩展
@propertyWrapper
struct UserDefaultsWrapper<T> {
    var key: String
    var defaultValue : T
    
    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }
    
    var wrappedValue: T {
        get {
            return UserDefaults.standard.value(forKey: key) as? T ?? defaultValue
        }
        
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

struct PropertyWrapperView: View {
    
    @UserDefaultsWrapper("hadShownUserGuide", defaultValue: false)
    static var hadShownUserGuide : Bool
    
    @State private var showText = PropertyWrapperView.hasShownUserGuide ? "已经展示" : "没有展示过"
    
    var body: some View {
        Button(action: {
            if (!PropertyWrapperView.hasShownUserGuide) {
                PropertyWrapperView.hasShownUserGuide = true
                self.showText = "已经展示"
            }
        }) {
            Text(self.showText)
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容