Swift-ui 2

class Contact: ObservableObject {
@Published var name: String
@Published var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1
return age
}
}
let john = Contact(name: "John Appleseed", age: 24)
cancellable = john.objectWillChange
.sink { _ in
print("\(john.age) will change")
}
print(john.haveBirthday())
这个属于combine的内容, 来自这儿的几点建议
- Use @State for simple properties that belong to a single view. They should usually be marked private. @State局限于一个view,不要用于接口
- Use @ObservedObject for complex properties that might belong to several views. Any time you’re using a reference type you should be using @ObservedObject for it.ObservedObject用于几个view之间共享数据
- Use @EnvironmentObject for properties that were created elsewhere in the app, such as shared data. 这个更适合用于swiftui与外部的接口,包括presenter
View有一个扩展
@inlinable public func environmentObject<B>(_ bindable: B) -> some View where B : ObservableObject
从名字上可以看到属于环境变量
EnvironmentObject是swiftui,而ObservableObject属于combine。@frozen @propertyWrapper struct EnvironmentObject<ObjectType> where ObjectType : ObservableObject
@frozen struct LocalizedStringKey根据这儿的描述
- 我们可以直接提供一个Localizable.strings并添加: "key"="value"
- 然后就可以在直接使用如 Label("key)
- 但是我们在实际中发现一些问题,比如在一个pod而不是app中
OTF stands for Postscript-flavored OpenType.
TTF stands for Truetype-flavored Opentype.
各有利弊吧
default values are not (0,0,0,0), might be 20 for each
padding(.bottom, -130) other part will be 0
虽然两者都conforms to View, 但是他们并不像View,比如没有背景色
Changes the view’s proposed area to extend outside the screen’s safe areas.
Style Weight Size (points) Leading (points)
Large Title Regular 34 41
Title 1 Regular 28 34
Title 2 Regular 22 28
Title 3 Regular 20 25
Headline Semi-Bold 17 22
Body Regular 17 22
Callout Regular 16 21
Subhead Regular 15 20
Footnote Regular 13 18
Caption 1 Regular 12 16
Caption 2 Regular 11 13
Title is the name of the whole book or article
Headline is for chapter
Image(room.thumbnailImage).resizable()
.frame(width: 32.0, height: 32.0)
有趣的是这个地方并不需要resizable也能设frame
将UIKit View包装成 swiftui的 view
A wrapper for a UIKit view that you use to integrate that view into your SwiftUI view hierarchy.
protocol UIViewRepresentable : View where Self.Body == Never
这儿的意思是这个View不会有body
这个方法已经被废弃。其中mode有: 
- automatic:取决于前一个页面,可能是inline/large
- inline: 在一行
- large: title下下面 加大字码, 默认参数
选择inline虽然紧凑,但是背景无法全透明,而large就是全透明。因此废弃也是一件好事。不带displayMode参数的方法没有废除,也就是是说废弃了inline这个参数而已。更多的与Navigation Bar相关的方法
- func navigationBarHidden(Bool) -> some View
- func statusBar(hidden: Bool) -> some View
比较有趣的是这个:
func navigationTitle<V>(_ title: () -> V) -> some View where V : View ,可以使用一个自定义的view。
一个container最多只能有10个直接的subviews,否则会出现编译错误。我估计是这个函数只写了十个参数 哈哈
- 可以通过Group 避免
- List没有这个限制
- 应该是一种静态限制(也就是编译的时候检查)
当自定义View的时候,可以给View添加一个init函数,当然可以带参数,实现的View是一个struct,只是conforms to View
看到apple给出的一个例子是:ScrollView + HStack + ForEach
- List 只能vertical
- ScrollView 可以是两个方向
- List is a View, but ForEach is not.
Toolbar变得很有意思,比如支持NavigationBar

.toolbar {
ToolbarItem(placement: .navigation) { Button("X") { }}
}
之前我们一般是 .bottomBar
这儿有一个Image 的tut
在UIKit的体系里面集成swiftui的View,也就是把一个swiftui的View包装在一个UIHostintController下,让这个View作为VC的view。
这儿说了如何集成
- let controller = UIHostingController(rootView: ...)
-
addChild(controller)
view.addSubview(controller.view)
controller.didMove(toParent: self)
----
比较有意思的这个UIHostingController有好几个init方法,其中一个是
init(nibName: String?, bundle: Bundle?)
言下之意是 这个UIHostingView不仅可以用在swiftui上,还可以用在传统的uikit上。
----
action需要额外处理,比如参数等,会有点麻烦,需要形成统一的处理方式的话会好一点
这个接口是把一般的UIView包装成一个swift-ui的View,注意,是UIView而不是UIViewController。这个定义很奇怪:我估计是可以实现一个任意类型的Coordinator。这儿说Void是默认类型
associatedtype Coordinator = Void
func makeCoordinator() -> Self.Coordinator
Coordinator的意思是协调人,第三方
---
tutorial 里面的MapView
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ uiView: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
uiView.setRegion(region, animated: true)
}

- func makeUIView(context: Self.Context) -> Self.UIViewType 这个是范型和associatetype
- Context: 这就是前面那个coordinate,没有实现,默认就是Void。有些时候需要提供一个自己的实现
上面这个例子有点不明白的是:MKMapView是一个UIView,并不是一个VC,为什么居然可以响应用户输入? 
答案: UIView当然可以响应输入,不如UIButton,一般的UIView可以通过,
- gestureRecognizerShouldBegin
- touchesBegan/touchMoved/touchEnded
来响应处理消息。
UIView/UIViewController 都是UIResponder的派生类,在消息链上其实是一样的。我们通常会把整个page当作一个UIController+他的view,但是一个UIViewController本身是可以包含子的UIViewController。
iOS的UIView/UIViewController并不完全是MVC的View和Controller。我们把一个Button的处理事件放在其VC里面,只是一种习惯。
VC的另一个很重要的作用是Navigation,这是View不具备的。

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store