SwiftUI
- SwiftUI 是一种基于Swift的强大能力,简单创新的构建用户界面的方法,并且可以运行在苹果所有的平台上
SwiftUI - 声明式语法
- SwiftUI采用声明式语法,因为你可以简单声明你的用户界面
- Xcode11提供了强大的设计工具,可以通过简单的拖拽用SwiftUI生成用户界面
- 只需要描述一次的布局-为你的视图声明任何状态的内容和布局,一旦状态发生改变,SwiftUI会自动更新视图的渲染
- 构建可复用的组件-将小型、独立视图组合到更大,更复杂的界面中。在任何为Apple平台所设计的应用之间,共享您的自定义视图
- 精简动画-创建平滑的动画就像调用单个方法一样简单。SwiftUI会在必要时自动计算并过渡动画
SwiftUI设计工具使用指南
创建项目
Stacks
如何使用SwiftUI构建可复用的组件
地标页例子
Image组件
structContentView: View { varbody: someView { 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()//留白 } } }
图片组件
structCircleImage: View { varbody: someView { //将图片剪切出一个圆Image("ymy").clipShape(Circle()) //加一个边框线 .overlay(Circle().stroke(Color.black, lineWidth: 4)) .shadow(radius: 10)//阴影 } }
地图组件
importSwiftUIimportMapKitstructMapView; UIViewRepresentable { //创建地图组件funcmakeUIView(context: Context) ->MKMapView { returnMKMapView(frame: .zero) } //对地图组件进行设置funcupdateUIView(_uiView: MKMapView, context: Context) { //圆明园的经纬度letlocation=CLLocationCoordinate2D(latitude: 40.00491139888854, longitude: 116.2896180152893) //展示范围letspan=MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5) letregion=MKCoordinateRegion(center: location, span: span) uiView.setRegion(region, animated: true) } }
如何使用SwiftUI实现动画
SwiftUI - 动画
- 在SwiftUI中,你可以将任意的改变过程封装进一个withAnimation块中。默认,SwiftUI会对这种改变采用fade in/out 的方式进行动画
structAnimationView: View { //状态 当属性改变时, 会进行重写渲染@StateprivatevarshowDetail=falsevarbody: someView { 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() } } }
在这里更改显示入口
深入理解SwiftUI:实现原理探秘
@propertyWrapper
- 通过property Wrapper机制,对一些类似的属性的实现代码做同一封装
- 通过@propertyWrapper可以移除掉一些重复或者类似的代码
@state
- 通过@State SwiftUI 实现了值的绑定、动态查找和View的自动重现绘制
- 课后题:查看源码,了解@Binding,@ObservedObject,@EnvironmentObject等装饰器的作用
extensionUserDefaults { publicenumKeys { staticlethadShownUserGuide="hadShownUserGuide" } varhadShownUserGuide: Bool { set { set(newValue, forKey: Keys.hadShownUserGuide) } get { bool(forKey: Keys.hadShownUserGuide) } } } structPropertyWrapperView: View { @StateprivatevarshowText=UserDefaults.standard.hasShownUserGuide?"已经展示" : "没有展示过"varbody: someView { Button(action: { if (!UserDefaults.standard.hasShownUserGuide) { UserDefaults.standard.hasShownUserGuide=trueself.showText="已经展示" } }) { Text(self.showText) } } }
- 使用propertyWrapper进行统一扩展
@propertyWrapperstructUserDefaultsWrapper<T> { varkey: StringvardefaultValue : Tinit(_key: String, defaultValue: T) { self.key=keyself.defaultValue=defaultValue } varwrappedValue: T { get { returnUserDefaults.standard.value(forKey: key) as?T??defaultValue } set { UserDefaults.standard.set(newValue, forKey: key) } } } structPropertyWrapperView: View { @UserDefaultsWrapper("hadShownUserGuide", defaultValue: false) staticvarhadShownUserGuide : Bool@StateprivatevarshowText=PropertyWrapperView.hasShownUserGuide?"已经展示" : "没有展示过"varbody: someView { Button(action: { if (!PropertyWrapperView.hasShownUserGuide) { PropertyWrapperView.hasShownUserGuide=trueself.showText="已经展示" } }) { Text(self.showText) } } }