219- iOS

swiftui
- View 是一个protocol,其中body函数 var body: some View { }
- 所有的可显示东西都是实现了View,比如Text,在API中很难发现实现了View,但的确如此。
@State
- 如果只在父子view里面share变量,@State + @Binding即可;而不需要enviroment
- @State 的willSet/didSet 并不能保证被swiftui组件触发;在代码中赋值会被触发
- 在init初始化或修改State: _x = State(initialValue: v),直接修改可能无效
swift
- TimeInterval 是一个 Double,typealias TimeInterval = Double
- 前台App如果需要收到自己的通知,需要注册UNUserNotificationCenterDelegate。通知发出之后会callback
- 直接format:date.formatted(date: .omitted, time: .shortened),简单的情况下可以不使用DateFormatter
- 我经常在lazy和computed var之间写错,lazy: lazy var x: X { }(),内部可以使用self。而computed: var x = {return } 内部也可以使用self
basic ios:
- ATS: App Transport Security, 也就是不允许http的访问
cookie相关:
- WKWebView 发起的请求不会自动带上存储于 NSHTTPCookieStorage 容器中的 Cookie,因此需要手动设置。
- iOS11.0推出WKHTTPCookieStore。WKHTTPCookieStore的使用和原理类似于NSHTTPCookieStorage;它将访问时获取的cookies自动存储在本地,下次访问时将自动携带相对应的cookie。
- WKHTTPCookieStore:每个网页实例一个:WKWebview- configuration.websiteDataStore.httpCookieStore
- WKNavigationDelegate 主要功能:决定是否走到下一网页decidePolicyFor,要么同意要么拒绝 decisionHandler(.allow/.cancel)
- 老的HTTPCookieStorage是一个shared对象
- WKWebsiteDataStore 包含两种对象,第一种是一个shared;另一种是包含在每个configuration上的,也就是每个WK一个。
调试:
- 输出对象地址 print(Unmanaged.passUnretained(someVar).toOpaque())
items:
- web服务器发送的是set-cookie: k=v;k1=v1;Expires=D;Domain=x, 存在多个
- 客户端发送请求的时候:Cookie: k1=v1&k2=v2
- Http协议规定(为了不给浏览器太大压力)1个Cookie最大4KB
- 1个服务器最多向1个浏览器保存20个Cookie -- 估计是最多20个 set-cookie
- 1个浏览器最多可以保存300个Cookie
iOS: WK获取cookie的方法
- WKHTTPCookieStore 可以获取全部的cookie,set或者delete
- 从http response的header中获取cookie HTTPCookie.cookies()
@AppStorage("showPreview") private var showPreview = true
使用的是UserDefaults
SceneStorage: 每个scene有自己的
@SceneStorage("text") var text = ""
使用的是和@State一样,而且会存储在UserDefaults里面。而且是自动存储。但是同步方面做得如何就不得而知了。- 只适用于primitive类型,不支持包括Date/List
@main
struct
TimerApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
#if os(macOS)
Settings {
SettingsView()
}
#endif
}
}
- UIApplicationDelegateAdaptor 使用UIKit的delegate,也许以后会改变
- App成为顶级对象
- Scene提供了生命周期管理; 每个平台提供不同的Scene实现
- Settings 和 WindowGroup是平行的; Settings只在Mac上: preference
- WindowGroup 和 Settings 之下都是View
- WindowGroup 相当于App的主界面;
- WindowGroup 还有Group的功能,还是一个简单的container
问题:
- 谁处理多窗口/多任务的事情:Scene
- 谁处理多屏幕的事情:外接屏幕的通知
UIKit:
- UIScreen 获取 main 或者是枚举所有的屏幕 screens;并能获取屏幕的大小等
- UIWindow
- UIView,有一个window对象,如果为nil则对象没有在显示屏上。
- UIWindow keyWindow makeKey 就是指获取输入焦点的意思
- UIScene/Scene 都是用来支持一个应用多个窗口的,而window则是显示的窗口,可大可小:
-
UIScreen -
UIWindowScene(->UIScene)- Scene
UIWindow - WindowGroup/Settings
UIView - View
UIWindowScene: 是中间部分,既可以获取关联的windows,也可以获取screen。UIWindow: 可以得到scene,也可以获得screen
UIScreen:并没有API直接获取其下所有的window或scene
外接屏幕通知:
- UIScreenDidConnect
- UIScreenDidDisconnect
Scene:使用 @Environment(\.scenePhase) private var scenePhase 来获取scene的状态。
UIScene:使用UISceneDelegate来callback状态,类似于UIApplicationDelegate
方法1: Circle.trim
Circle()
.trim(from: 0.25, to: 1.0) // 裁掉
.rotation(.degrees(-90)) // 旋转
.stroke(Color.black ,style: StrokeStyle(lineWidth: 3, lineCap: .butt, dash: [5,3], dashPhase: 10))
方法2: addArc
-
func foo() -> Int {
defer { doLast() }
defer { beforeLast() }
return x
}
- defer 在 return 的后面执行
- 即使抛出异常,defer也在异常抛出之后执行
- defer 可以多重,按照声明相反的顺序执行
- 因此 defer这个机制可以省略不少代码
self.layer.shadowOpacity = 0; 0: 不显示, 1:显示
方法1:
dicFrom.forEach { (key, value) in dicTo[key] = value }
方法2: merge/merging
let dictionary = ["a": 1, "b": 2]
let newKeyValues = ["a": 3, "b": 4]
// 前者优先
let keepingCurrent = dictionary.merging(newKeyValues) { (current, _) in current }
// ["b": 2, "a": 1]
// 后者优先
let replacingCurrent = dictionary.merging(newKeyValues) { (_, new) in new }
// ["b": 4, "a": 3]
merge 合并到前者
merging 原来的两个map不变
// append 单个
anArray.append("This String")
// append 多个
anArray += ["Moar", "Strings"]
anArray.append(contentsOf: ["Moar", "Strings"])
// 插入某个位置
anArray.insert("This String", at: 0)
// 插入一个数组
anArray.insert(contentsOf: ["Moar", "Strings"], at: 0)
方法1:
i++ 使用 i += 1, 但是 i += 1这个表达式没有返回值
方法2: 使用 inout 参数, 调用的时候 inc(&v),引用reference
// i++
func inc(_ v: inout Int) -> Int {
let p = v; v += 1
return p
}
// ++i
func inc(_ v: inout Int) -> Int {
v += 1; return v
}
方法3: 自定义扩展,prefix/postfix/inout/deferextension Int {
@discardableResult
static prefix func ++(x: inout Int) -> Int { // ++i
x += 1
return x
}
// i++ ; 返回当前值,然后递增
static postfix func ++(x: inout Int) -> Int { // i++
defer {x += 1}
return x
}

@discardableResult
static prefix func --(x: inout Int) -> Int { // --i
x -= 1
return x
}

static postfix func --(x: inout Int) -> Int { // i--
defer {x -= 1}
return x
}
}
如果是infix,中间操作符:
extension Vector2D: Equatable {
static func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
}
a..<b  表示 [a, b)
a...b 表示 [a, b]
没有 a..b
.overlay(Circle().stroke(Color.white, lineWidth: 4))- Circle 是 Shape(I),Shape是View(I)
- .stroke 作用于shape
overlay: 是建立在parent view上的,不能超出parent的范围
ZStack:所有的子view都是平等的
.overlay 更高级
struct RoundButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
ZStack {
Circle().fill()
configuration.label
.font(Font.system(.title3).bold().italic())
.foregroundColor(.white)
.padding(12)
}
.opacity(configuration.isPressed ? 0.9 : 1.0)
.scaleEffect(configuration.isPressed ? 0.9 : 1.0)
}
}
- Circle().fill() 用Button前景色填充,而且Circle外的地方不会响应
- Circle并不需要设置半径,而是使用frame,也就是说直径是width/height
- Color.green swiftui会把颜色直接当作一个view - SwiftUI treats colors as View instances, Color本身是一个struct,而且conforms to View
Large -- default: (手机选择-xsmall/small/medium/large/xlarge/xxlarge) 这就是accessbility里面可选择的6种large title, 34, 最大
title 1/2/3: 28/22/20 // title1就是title, title1比title2大
Headline: 17 // 大字标题
body: 17 - Semi-Bold // 其他字体都是 regular
foot note: 13
caption 1/2: 12/11 // 图片的说明文字
caption2 最小
.onReceive(NotificationCenter.default.publisher(for: xx), perform: { _ in
})
backboardd is a daemon that runs alongside the SpringBoard daemon.
SpringBoard is the standard application that manages the iPhone's home screen.
SpringBoard + backboardd 都是iPhone的桌面进程,配合使用。估计包括互相启动

--

--

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