俊瑶先森


  • 首页

  • 归档

  • 关于

swiftUI笔记之async&await实践MVVM网络请求

发表于 2023-05-22 |

实践

我们来实践一下使用MVVM模式,并使用async await进行网络请求。

XfOeyo

Library.swift

1
2
3
4
5
6
import Foundation

struct Common: Codable,Hashable {
var act: String
var prompt: String
}

LibraryViewModel.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

import Foundation

@MainActor
class LibraryViewModel: ObservableObject {
@Published var commons: [Common]
init(commons: [Common]) {
self.commons = commons
}
func getCommons() async {
self.commons = []
guard let url = URL(string: "https://carteclip.com/api/v1/ama/prompts") else {
print("URL无效,请检查输入~")
return
}
do {
var request = URLRequest(url: url)
request.setValue("zh", forHTTPHeaderField: "prefer-language")
let (data, _) = try await URLSession.shared.data(
for: request
)
if let decodedResponse = try? JSONDecoder().decode([Common].self, from: data) {
self.commons = decodedResponse
}
} catch {
print("数据解码失败,请检查~")
}
}
}

LibraryView.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

import SwiftUI

struct LibraryRow: View {
var common: Common
var body: some View {
VStack(alignment: .leading) {
Spacer()
Text(common.act)
.listRowSeparator(.hidden)
.font(.system(size: 18))
.frame(maxWidth: .infinity, alignment: .leading)

Spacer()
Text(common.prompt)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.system(size: 15))
.lineLimit(3)
Spacer()
}
}

}

struct LibraryView: View {
@ObservedObject var viewModel: LibraryViewModel
var body: some View {
List(viewModel.commons,id: \.self) { result in
Section{
LibraryRow(common:result)
.listRowSeparator(.hidden)
}
}.task {
await viewModel.getCommons()
}.refreshable {
await viewModel.getCommons()
}
}
}

struct LibraryView_Previews: PreviewProvider {
static var previews: some View {
LibraryView(viewModel: .init(commons: []))
}
}

swiftUI笔记之EnvironmentObject之暗黑模式适配实践

发表于 2023-05-11 |

Pjqg7f

我们以暗黑模式的适配来实践EnvironmentObject

暗黑模式适配

定义AppSetting,设置 @Published var darkModeSettings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class AppSetting: ObservableObject {
@Published var darkModeSettings: Int = UserDefaults.standard.integer(forKey: "darkMode") {
didSet {
UserDefaults.standard.set(self.darkModeSettings, forKey: "darkMode")
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first as? UIWindowScene
let window = windowScene?.windows.first
switch self.darkModeSettings {
case 0:
window?.overrideUserInterfaceStyle = .unspecified
case 1:
window?.overrideUserInterfaceStyle = .light
case 2:
window?.overrideUserInterfaceStyle = .dark
default:
window?.overrideUserInterfaceStyle = .unspecified
}
}
}
}

传入 .environmentObject(AppSetting())

1
2
3
4
5
6
7
8
@main
struct tableViewApp: App {
var body: some Scene {
WindowGroup {
ContentView().environmentObject(AppSetting())
}
}
}

使用@EnvironmentObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

struct SettingsView: View {
@EnvironmentObject var appSettings: AppSetting

var body: some View {
NavigationStack {
List {
Section {
HStack{
Button {
appSettings.darkModeSettings = 0
} label: {
Text("跟随系统").foregroundColor(.primary)
}
Spacer()
if(appSettings.darkModeSettings == 0){
Image(systemName: "checkmark")
}
}
HStack{
Button {
appSettings.darkModeSettings = 1
} label: {
Text("白").foregroundColor(.primary)
}
Spacer()
if(appSettings.darkModeSettings == 1){
Image(systemName: "checkmark")
}
}
HStack{
Button {
appSettings.darkModeSettings = 2
} label: {
Text("暗黑").foregroundColor(.primary)
}
Spacer()
if(appSettings.darkModeSettings == 2){
Image(systemName: "checkmark")
}

}

} header: {
Text("主题设置")
.textCase(nil)
}
}
.listStyle(.insetGrouped)
.navigationTitle("设置")
}
}
}

相关链接阅读

SwiftUI: 全局状态管理

swiftUI笔记之ObservedObject与StateObject差别实践

发表于 2023-05-11 |

@StateObject 修饰的对象与 @ObservedObject 一样,都需要遵循 Observable 协议,功能也类似。区别在于,@StateObject 修饰的对象只会在所属的 View 中创建一次并在 View 的生命周期内存储相应的状态,而 @ObservedObject 修饰的对象会随着 View 的重绘生成新的对象,不会在 View 的生命周期内存储该对象的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import SwiftUI

class Counter: ObservableObject {
@Published var count: Int = 0
}
struct StateObjectDemo: View {
@State private var buttonTitle = "Tap me"
var body: some View {
ItemList()
}
}
struct ItemList: View {
@State private var items = ["hello", "world"]
var body: some View {
VStack {
Button("Append item to list") {
items.append("test")
}
List(items, id: \.self) { name in
Text(name)
}
CounterView1()
CounterView2()
}
}
}


struct CounterView1: View {
// StateObject示例
@StateObject var counter1 = Counter()
var body: some View {
VStack {
Text("StateObject count: \(counter1.count)")
Button("点击StateObject➕1") {
counter1.count += 1
}
}
}
}

struct CounterView2: View {
// ObservedObject示例
@ObservedObject var counter2 = Counter()
var body: some View {
VStack {
Text("ObservedObject count: \(counter2.count)")
Button("点击ObservedObject➕1") {
counter2.count += 1
}
}
}
}

struct StateObjectDemo_Previews: PreviewProvider {
static var previews: some View {
StateObjectDemo()
}
}

如上代码所示,当我们点击 CounterView1 和 CounterView2 中的按钮时,会给相应的 Counter 实例的 count 属性加 1,一旦我们点击 “Append item to list” 按钮,View 会执行重绘,这时 CounterView2 中的 count 会重置为 0,而 CounterView1 中使用 @StateObject 修饰的对象中的 count 仍然持有当前的数据状态。

那么我们应该在什么场景下分别使用这两个属性包装器呢?

在 View 的生命周期内,需要一直持有并存储对象的状态时,使用 @StateObject 修饰。基本上,绝大多数情况下的 viewModel 都会是这种情况。

只有在少数情况下,View 不需要一直持有该对象,该对象的状态会随着外界的条件改变而刷新自己时,我们才用到 @ObservedObject 修饰,比如上面的例子,如果我们要求点击 “Append item to list” 按钮时,count 就重置,就需要用 @ObservedObject 修饰了。

swiftUI笔记之页面跳转

发表于 2023-05-06 |

push && present

qquebh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

import SwiftUI

struct NavigationStackView: View {
@State var presentSheetKey = false
@State var presentFullScreenCoverKey = false
var body: some View {
NavigationStack {
List {
Section {
NavigationLink(destination: PushView(),label: {Text("I am Root. Tap for Push View -1")})

NavigationLink{
PushView()
} label: {
Text("I am Root. Tap for Push View -2")
}
NavigationLink("I am Root. Tap for Push View -3", destination: PushView())

NavigationLink("I am Root. Tap for Push View -4") {
PushView()
}
} header: {
Text("push")
}
Section {
Button {
self.presentSheetKey.toggle()
} label: {
Text("sheet").foregroundColor(.primary)
}

Button {
self.presentFullScreenCoverKey.toggle()
} label: {
Text("fullScreenCover").foregroundColor(.primary)
}
} header: {
Text("present")
}
}.navigationTitle("view跳转")
}
.sheet(isPresented: $presentSheetKey) {
//非全屏模式
PresentView()
}
.fullScreenCover(isPresented: $presentFullScreenCoverKey, content: {
//全屏模式
PresentView()
})
}
}

struct PushView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
Image(systemName: "phone")
.resizable()
.frame(width: 80, height: 80)
Text("hello")
.font(.system(.title, design: .rounded))
.fontWeight(.black)
Spacer()
Button("Here is Detail Push View. Tap to go back."){
dismiss()
}
}
}
}

struct PresentView: View {
//用于退出该界面
//@Environment(\.presentationMode) var presentationMode
@Environment(\.dismiss) var dismiss
var body: some View {
VStack(alignment: .center, spacing: nil, content: {
Spacer()
HStack(content: {
Spacer()
})
Button("Here is Detail Present View. Tap to go back.") {
dismiss()
// self.presentationMode.wrappedValue.dismiss()
}
.font(.system(size: 20))
.foregroundColor(.red)
.background(Color.white)
Spacer()
})
.background(Color.gray)
.navigationBarTitle("presentView", displayMode: .inline)
}
}

struct NavigationStackView_Previews: PreviewProvider {
static var previews: some View {
NavigationStackView()
}
}

相关

SwiftUI:页面跳转和导航设置

swiftUI笔记之TabView实践

发表于 2023-04-22 |

E9R7p0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//
// ContentView.swift
// tableView
//
// Created by junyao on 2023/4/22.
//

import SwiftUI
import TabBar

struct ContentView: View {
enum TabItems: Int {
case editor, notes, share, settings
}
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
EditorView()
.badge(10)
.tabItem {
Label("对话", systemImage: "pencil.circle")
Text("Editor")
}.tag(TabItems.editor.rawValue)
.onTapGesture {
selectedTab = TabItems.editor.rawValue
}

NotesView()
.tabItem {
Label("指令库", systemImage: "note.text")
Text("Notes")
}.tag(TabItems.notes.rawValue)
.onTapGesture {
selectedTab = TabItems.notes.rawValue
}

SettingsView()
.tabItem {
Label("设置", systemImage: "gearshape")
Text("Settings")
}.tag(TabItems.settings.rawValue)
.onTapGesture {
selectedTab = TabItems.settings.rawValue
}
}.accentColor(.black).tint(.black)
.onAppear(perform: {
//修改未选择的项的颜色
UITabBar.appearance().unselectedItemTintColor = UIColor(Color.gray)
})
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

相关

SwiftUI——如何修改TabView的各种属性(包括tabItem的属性),例如颜色、位置、大小等

Stable Diffusion之模型篇

发表于 2023-04-18 |

Stable Diffusion 模型资源

  1. Hugging Face
  2. Civitai

模型安装

Stable Diffusion Web Ui安装过程中会默认下载Stable Diffusion v1.5模型,名称为v1-5-pruned-emaonly。如果想用最新的Stable Diffusion v2.1,可以从Hugging Face上下载官方版本stabilityai/stable-diffusion-2-1。下载后将模型复制到models目录下的Stable-diffusion目录即可。完成后点击页面左上角的刷新按钮,即可在模型下拉列表中看到新加入的模型。

除了标准模型外,Stable Diffusion还有其他几种类型的模型,models目录下每一个子目录就是一种类型的模型,其中用的最多的是LoRA模型。

我们来实践几个模型

基础大模型

  • v1-5-pruned-emaonly.ckpt
    Stable Diffusion基础大模型,原则上所有其他大模型都在这个模型基础上再微调出来的

  • chilloutmix_NiPrunedFp32Fix.safetensors
    AI真人基础模型,一般搭配LoRA小模型

  • Anything、Waifu、novelai、Counterfeit
    二次元漫画型

LoRA示例

LoRA(Low-Rank Adaptation)模型是小型稳定扩散模型,可对标准模型进行微调。它通常比标准模型小10-100倍,这使得LoRA模型在文件大小和训练效果之间取得了很好平衡。LoRA无法单独使用,需要跟标准模型配合使用,这种组合使用方式也为Stable Diffusion带来了强大的灵活性。

下面我们使用 chilloutmix大模型 + LoRA的微调小模型koreanDollLikeness来试试

LoRA模型下载后需要放到Lora目录中,使用时在提示中加入LoRA语法,语法格式如下:

1
<lora:filename:multiplier>

filename是LoRA模型的文件名(不带文件后缀)

multiplier是LoRA 模型的权重,默认值为1,将其设置为 0 将禁用该模型。

Prompt
选择好模型后,我们开始设计prompt。首先我们引入LoRA

1
<lora:koreanDollLikeness:0.66>

然后定义生成图片的风格,我们希望超写实风,可以用如下关键词:

1
best quality, ultra high res, (photorealistic:1.4)

其中photorealistic我们赋予较高的权重1.4。

接着来定义图片的主体内容,这里我将希望图片中出现的元素都做个权重增强:

1
1girl, thighhighs, ((school uniform)),((pleated skirt)), ((black stockings)), (full body), (Kpop idol), (platinum blonde hair:1), ((puffy eyes))

最后,修饰一些表情、姿势的细节:

1
smiling, solo focus, looking at viewer, facing front

这样我们完整的promt是:

1
<lora:koreanDollLikeness:0.66>, best quality, ultra high res, (photorealistic:1.4), 1girl, thighhighs, ((school uniform)),((pleated skirt)), ((black stockings)), (full body), (Kpop idol), (platinum blonde hair:1), ((puffy eyes)), smiling, solo focus, looking at viewer, facing front

Negative prompt
我们还需要提供Negative prompt去除我们不想要的风格和元素:

1
paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, glan

这里主要剔除了绘画风、简笔画、低质量、灰度图,同时去除雀斑、痤疮等皮肤瑕疵。

参数设置
为了让图片生成得更加真实自然,我们需要对参数做一些调整,需要调整的参数如下:

Sampler: DPM++ SDE Karras
Sample Steps: 28
CFG scale: 8
Size: 512×768

dddd44d

常见问题

Q1:SD:2.1安装报错

1
NansException: A tensor with all NaNs was produced in VAE. This could be because there's not enough precision to represent the picture. Try adding --no-half-vae commandline argument to fix this.

解决

1
Settings > Stable Diffusion > Enable option "Upcast cross attention layer to float32" (at Stable Diffusion localhost server).

swiftUI笔记之List实践

发表于 2023-04-17 |

简单文字列表

8oQgNf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//
// NotesView.swift
// tableView
//
// Created by junyao on 2023/4/22.
//

import SwiftUI

struct Message: Identifiable {
var id = UUID()
var title: String
var des: String
}

// 定义数组,存放数据
var Messages = [
Message(title: "充当Linux终端", des: "我想让你充当 Linux 终端。我将输入命令,您将回复终端应显示的内容。我希望您只在一个唯一的代码块内回复终端输出,而不是其他任何内容。不要写解释。除非我指示您这样做,否则不要键入命令。当我需要用英语告诉你一些事情时,我会把文字放在中括号内[就像这样]。我的第一个命令是 pwd"),
Message(title: "充当英翻中", des: "下面我让你来充当翻译家,你的目标是把任何语言翻译成中文,请翻译时不要带翻译腔,而是要翻译得自然、流畅和地道,使用优美和高雅的表达方式。请翻译下面这句话:“how are you ?"),
Message(title: "担任面试官", des: "我想让你担任Android开发工程师面试官。我将成为候选人,您将向我询问Android开发工程师职位的面试问题。我希望你只作为面试官回答。不要一次写出所有的问题。我希望你只对我进行采访。问我问题,等待我的回答。不要写解释。像面试官一样一个一个问我,等我回答。我的第一句话是“面试官你好"),
Message(title: "充当旅游指南", des: "我想让你做一个旅游指南。我会把我的位置写给你,你会推荐一个靠近我的位置的地方。在某些情况下,我还会告诉您我将访问的地方类型。您还会向我推荐靠近我的第一个位置的类似类型的地方。我的第一个建议请求是“我在上海,我只想参观博物馆。"),
Message(title: "充当讲故事的人", des: "我想让你扮演讲故事的角色。您将想出引人入胜、富有想象力和吸引观众的有趣故事。它可以是童话故事、教育故事或任何其他类型的故事,有可能吸引人们的注意力和想象力。根据目标受众,您可以为讲故事环节选择特定的主题或主题,例如,如果是儿童,则可以谈论动物;如果是成年人,那么基于历史的故事可能会更好地吸引他们等等。我的第一个要求是“我需要一个关于毅力的有趣故事。"),
]

struct NotesView: View {
var body: some View {
List {
ForEach(Messages) { Message in
Section {
Text(Message.title)
.listRowSeparator(.hidden)
.font(.title3)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(1)
Text(Message.des)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(3)
.padding(1)
}.padding()
}.listRowInsets(EdgeInsets())
}
}
}

struct NotesView_Previews: PreviewProvider {
static var previews: some View {
NotesView()
}
}

列表操作 onDelete & onMove & ContextMenu & ActionSheets

完整实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import SwiftUI
struct Message: Identifiable {
var id = UUID()
var title: String
var last: String
}
// 定义数组,存放数据
var Messages = [
Message(title: "充当英翻中", last: "很好,让我们开始为想要减肥的人设计一个锻炼计划。首先,我们需要了解他们的目标和当前的健身水平。您可以问他们关于以下问题的信息:您的身高、体重和BMI(身体质量指数)是多少?您每周进行多少次有氧运动和力量训练?您每次进行运动的时间是多长?您的饮食习惯是什么?您是否有任何特殊的饮食限制?您的工作和日常活动水平是什么?一旦您了解了他"),
Message(title: "担任私人教练", last: ""),
Message(title: "随便聊聊", last: ""),
Message(title: "随便聊聊", last: ""),
Message(title: "随便聊聊", last: "好的,这是一个小学生的笑话:"),
]
struct DialogueView: View {
@State var messagesItems = Messages
@State var showActionSheet = false

var body: some View {
NavigationView{
List {
ForEach(messagesItems) { Message in
HStack {
Image("dialogue")
.resizable()
.renderingMode(.template)
.foregroundColor(.gray)
.frame(width: 40, height: 40)
VStack {
Text(Message.title)
.foregroundColor(.black)
.listRowSeparator(.hidden)
.font(.system(size: 17).weight(.light))
.frame(maxWidth: .infinity, alignment: .leading)
.padding(1)
Text(Message.last)
.foregroundColor(.gray)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.system(size: 15))
.lineLimit(1)
.padding(1)
}
Image("drag")
.resizable()
.frame(width: 20, height: 20)
}.contextMenu {
Button(action: {
// 点击删除
// self.delete(item: Message)
// 点击打开ActionSheet弹窗
self.showActionSheet.toggle()
}) {
HStack {
Text("删除")
Image(systemName: "trash")
}
}
}
// ActionSheet弹窗
.actionSheet(isPresented: self.$showActionSheet) {
ActionSheet(
title: Text("你确定要删除此项吗?"),
message: nil,
buttons: [
.destructive(Text("删除"), action: {
//点击删除
self.delete(item: Message)
}),
.cancel(Text("取消"))
])
}

}
.onDelete(perform: deleteRow)
.onMove(perform: moveItem)
}
.navigationBarItems(leading:
HStack {
Image(systemName: "trash")
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(.gray)
},trailing:
HStack {
Button("新对话") {
print("Specials tapped!")
}
}
)
}
}
// 滑动删除方法
func deleteRow(at offsets: IndexSet) {
messagesItems.remove(atOffsets: offsets)
}
// 拖动排序方法
func moveItem(from source: IndexSet, to destination: Int) {
messagesItems.move(fromOffsets: source, toOffset: destination)
}
//contextMenu 删除的方法
func delete(item Message: Message) {
if let index = self.messagesItems.firstIndex(where: { $0.id == Message.id }) {
self.messagesItems.remove(at: index)
}
}
}

struct DialogueView_Previews: PreviewProvider {
static var previews: some View {
DialogueView()
}
}

onDelete & onMove
48yxb4

1
2
3
4
5
6
7
8
9
10
11
.onDelete(perform: deleteRow)
.onMove(perform: moveItem)

// 滑动删除方法
func deleteRow(at offsets: IndexSet) {
messagesItems.remove(atOffsets: offsets)
}
// 拖动排序方法
func moveItem(from source: IndexSet, to destination: Int) {
messagesItems.move(fromOffsets: source, toOffset: destination)
}

ContextMenu
hLrB9B

1
2
3
4
5
6
7
8
9
10
11
.contextMenu {
    Button(action: {
        // 点击删除
self.delete(item: Message)
    }) {
        HStack {
            Text("删除")
            Image(systemName: "trash")
        }
    }
}
1
2
3
4
5
6
    //删除的方法
    func delete(item Message: Message) {
        if let index = self.messagesItems.firstIndex(where: { $0.id == Message.id }) {
            self.messagesItems.remove(at: index)
        }
    }

ActionSheets
vV7cEY

1
2
3
4
5
6
7
8
9
10
11
12
13
.contextMenu {
Button(action: {
// 点击删除
// self.delete(item: Message)
// 点击打开ActionSheet弹窗
self.showActionSheet.toggle()
}) {
HStack {
Text("删除")
Image(systemName: "trash")
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
.actionSheet(isPresented: self.$showActionSheet) {
ActionSheet(
title: Text("你确定要删除此项吗?"),
message: nil,
buttons: [
.destructive(Text("删除"), action: {
//点击删除
self.delete(item: Message)
}),
.cancel(Text("取消"))
])
}

swiftUI笔记之Identifiable

发表于 2023-04-17 |

在 SwiftUI 中,如果你要使用列表(List)或者集合视图(CollectionView),你需要使用 Identifiable 协议来确保每个元素都具有唯一的标识符。如果你的数据类型本身已经有了唯一标识符(比如一个唯一的 ID 字段),那么可以通过让该数据类型遵循 Identifiable 协议并实现 id 属性来实现。

1
2
3
4
struct Person: Identifiable {
let id: String
let name: String
}

然后,在你的列表或者集合视图中,你可以像这样使用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct ContentView: View {
let people = [
Person(id: "1", name: "Alice"),
Person(id: "2", name: "Bob"),
Person(id: "3", name: "Charlie"),
]

var body: some View {
List(people) { person in
Text(person.name)
}
}
}

这里的 List 会自动使用 id 属性来确定每个元素的唯一性,所以你不需要手动指定标识符。
如果你的数据类型没有唯一标识符,你也可以使用一个自动生成的标识符。在这种情况下,你可以使用 id() 函数来为每个元素生成一个唯一的标识符。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Person {
let name: String
}

struct ContentView: View {
let people = [
Person(name: "Alice"),
Person(name: "Bob"),
Person(name: "Charlie"),
]

var body: some View {
List(people, id: \.self) { person in
Text(person.name)
}
}
}

这里的 id: .self 会告诉 SwiftUI 使用每个元素本身作为标识符。

Stable Diffusion之Prompt篇

发表于 2023-04-16 |
  • Photo Realistic 高清照片风格

    1
    raw photo, photorealistic, masterpiece, best quality, hires, intricate details, reflections, photographed on a Canon EOS R5, 50mm lens, F/2.8, HDR, 8k resolution, ray-tracing,
  • Negative Prompt for Beauty

    1
    EasyNegative, bad_prompt_version2, bad-hands-5, ng_deepnegative_v1_75t, (watermark:1.6), (text:1.4), (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, (outdoor:1.6), manboobs, backlight,(ugly:1.331), (duplicate:1.331), (morbid:1.21), (mutilated:1.21), (tranny:1.331), mutated hands, (poorly drawn hands:1.331), blurry, (bad anatomy:1.21), (bad proportions:1.331), extra limbs, (disfigured:1.331), (more than 2 nipples:1.331), (missing arms:1.331), (extra legs:1.331), (fused fingers:1.61051), (too many fingers:1.61051), (unclear eyes:1.331), bad hands, missing fingers, extra digit, (futa:1.1), bad body, pubic hair, glans, (nipples:1.4), (nsfw:1.4), (nude:1.6),nsfw,
  • Style 风格

    Style Description Style Description
    artbook 原画 game_cg 游戏CG
    tachi-e 立绘样式 comic 漫画
    dakimakura 抱枕 cosplay 角色扮演
    photo 照片 personification 拟人
    realistic 现实 sketch 素描
    traditional_media 手绘 sketch 手绘
  • Lighting Style

    Lighting Description Lighting Description
    Bloom 开花;绽放 God rays 神光;天光
    Hard shadows 硬阴影 Studio lighting 工作室照明
    Soft lighting 柔和照明;柔光 Diffused lighting 散射照明;漫射光
    Rim lighting 边缘照明;边缘光 Volumetric lighting 体积照明
    Specular lighting 镜面照明;高光 Cinematic lighting 电影照明
    Luminescence 发光;自发光 Translucency 半透明性
    Subsurface scattering 亚表面散射 Global illumination 全局照明
    Indirect light 间接光 Radiant light rays 辐射光线
    Bioluminescent details 生物发光细节 Ektachrome 依可透
    Glowing 发光的 Shimmering light 闪闪发光的光
    Halo 暈;光圈 Iridescent 彩虹色的;虹彩般的
    Backlighting 背光;逆光 Caustics 光照色彩变化效应
  • Hair 头发

    Hair Description Hair Description
    multicolored hair 多彩的头发 hime cut 姬发式
    ahoge 呆毛 braid 辫子
    asymmetrical hair 半边刘海 french braid 法式辫
    blunt bangs 齐刘海 braided ponytail 编织马尾辫
    parted bangs 分开的刘海 hair intakes 进气口发型
    side swept bangs 朝一个方向的刘海 hair behind ear 耳后发
    curtained hair 窗帘式发型 hair over shoulder 披肩发
    colored inner hair 内侧颜色 hair bun 团子头
    streaked hair 条染 double bun 双团子头
  • Face 脸

    Face Description Face Description
    light smile 微笑 seductive smile 诱惑笑
    grin 露齿而笑 laughing 笑
    excited 兴奋 smirk 微笑
    smug 得意 屑 embarrassed 害羞
    shy 害羞 blush 脸红
    sad 悲伤的 pout 别扭 努嘴
    sigh 叹气 angry 生气
    annoyed 苦恼的 frown 皱眉/蹙额
    wide eyed 睁大眼睛 jitome 鄙夷的眼神
    serious 严肃 smirk 认真
    scowl 锐利 crazy 疯狂的
    dark_persona 黑化的 naughty_face 下流的表情
    endured_face 忍耐的表情 ahegao 阿黑颜
  • Cloth 衣着

    Cloth Description Cloth Description
    side-tie bikini bottom 系带比基尼裤 detached collar 分离式衣领,只有衣领
    front-tie bikini top 系带比基尼上衣 cuffs 袖口
    frilled bikini 褶边比基尼 midriff 露腰上衣
    string bikini 细带比基尼 crop top 露腰上衣
    highleg bikini 高腰比基尼 clothing cutout 剪切过的衣服
    o-ring bikini 有环的比基尼 breast curtains 胸帘
    sling bikini 吊带比基尼 versus bikini 宝石比基尼
    mismatched bikini 不太懂 collared shirt 带领衬衫
    revealing clothes 暴露的衣服 vest 马甲背心
    see-through 半透明衣服 puffy sleeves 蓬松袖子
    garter straps 吊带袜 peaked cap 宽檐帽
    cheerleader 啦啦队 pelvic curtain 骨盆帘
    pleated skirt 百褶裙 halter shirt 吊带衬衫
    suspender skirt 吊带裙 ribbed sweater 罗纹毛衣
    leotard 连体紧身衣 bodysuit 连体紧身衣
    tank top 汗衫 torn clothes 撕破的衣服
    taut clothes 绷紧的衣服 impossible clothes 不可能的衣服
    string panties 细绳内裤 pantyhose 连裤袜
    panties under pantyhose 连裤袜下内裤 competition swimsuit 竞泳
    undersized clothes 过小的衣服 cropped jacket 短外套
    plugsuit 插入服,eva那种紧身衣 crotchless panties 开裆内裤
    legwear 腿上一切 serafuku 水手服
    sailor collar 水手领 kimono 和服
    yukata 浴衣 japanese clothes 日式服装
    sports bra 运动上衣 bike shorts 骑行裤
    lolita fashion Lolita衣服 race queen 赛车女郎
    skindentation 贴身的? raglan sleeves 连肩衣袖
    sleeves past fingers 手指过长的袖子 sleeves past wrist 手腕过长的袖子
    bunnysuit 兔女郎 reverse bunnysuit 逆兔女郎
    reverse outfit 逆着穿的衣服 straitjacket 拘束衣
    sleeve skirts 袖裙 covered nipples 凸激
  • Accessory 装饰

    Accessory Description Accessory Description
    tassel 流苏 wristband 腕带
    epaulettes 肩章 spaghetti strap 细肩带
    ascot 宽领带 bridal gauntlets 长手套
    trim 包边 criss-cross halter 交错绕颈系带
    bowtie 蝴蝶结领带 halterneck 绕颈系带
    neck ribbon 系带领 harness 背带,挽具
    lapels 翻领 corset 束腰
    frills 荷叶边 underbust 束腰
    buckle 扣带 necklace 项链
    belt buckle 皮带扣 sailor collar 水手领
    chest harness 胸带 hairband 发带
    suspenders 肩吊带 vambraces 护腕
    lace-trimmed 蕾丝边 elbow gloves 肘部手套
    veil 面纱 interface headset 明日香头上那个角
    tinted eyewear 有色眼镜 chest jewel 胸前珠宝
    pocket watch 怀表 tiara 头冠
    hachimaki 钵卷,日式头带 fake animal ears 假动物耳朵
    headgear 头上机器 hat bow 帽子蝴蝶结
    sweatdrop 汗珠 pompom(clothes) 衣服上的毛球
    water drop 水滴 pompom(cheerleading) 啦啦队彩球
    falling petals 掉落的花瓣 neck ring 颈环
    wrist cuffs 手腕袖口 stitches 缝线
    chain 锁链 visor cap 游客帽
    o-ring 圆环装饰 scrunchie 发圈束
    oni horns 鬼角 surgical mask 医用口罩
    mouth mask 口罩

Pose 姿势

  • Full body 全身

    Body Pose Description Body Pose Description
    leaning forward 前倾 undressing 脱衣服
    fetal position 婴儿姿势(侧躺手脚曲着) against wall 靠墙
    on_stomach 趴着 squatting 蹲下
    lying 躺着 sitting 坐
    seiza 正坐 wariza/w-sitting 割坐
    yokozuwari 侧身坐 indian_style 盘腿
    leg_hug 抱腿 walking 走
    running 跑 straddle 跨坐
    straddling 跨立 kneeling 下跪
    smoking 抽烟 arm_support 用手支撑住
    caramelldansen niconiconi princess_carry 公主抱
    fighting_stance 战斗姿态 upside-down 颠倒的
    top-down_bottom-up 趴着翘臀 bent_over 翘臀姿势
    all_fours 四肢趴地 arched_back 弓身体
    back-to-back 背对背 symmetricalhandpose 手对手
    eye_contact 眼对眼(对视) symmetrical_docking 2女胸部贴在一起
    hug 拥抱 lap_pillow 膝枕
    sleeping 睡觉 bathing 洗澡
    mimikaki 掏耳勺 holding_hands 牵手
  • Head 头

    Head Pose Description Head Pose Description
    head tilt 歪头 turning around 回头
    looking back 回头看 looking down 向下看
    looking up 向上看 smelling 闻
  • Hand/Arm 手/手臂

    Hand Pose Description Hand Pose Description
    handtomouth 手放在嘴边 arms_crossed 手交叉于胸前
    arm at side 手放头旁边 hand on hip 手放臀
    arms behind head 手放脑后 hand on another’s hip
    arms behind back 手放后面 handonhip 单手插腰
    hand on own chest 手放在自己的胸前 handsonhips 双手叉腰
    arms up/hands up 举手 stretch 伸懒腰
    armpits 举手露腋 leg hold 手把腿抓着
    grabbing 抓住 holding 拿着
    fingersmile 用手指做出笑脸 skirt lift 掀起裙子
    shirt lift 掀起上衣 adjusting_thighhigh 调整过膝袜
    hair_pull 拉头发 hair scrunchie 撮头发
  • Gestures 手势

    Gestures Description Gestures Description
    v/peace_symbol ✌ thumbs_up 翘大拇指
    middle_finger 比出中指 cat_pose 猫爪手势
    finger_gun 手枪手势 shushing 嘘手势
    waving 招手 salute 敬礼
    spread_arms 张手
  • Leg 腿

    Leg Pose Description Leg Pose Description
    spread legs 张开腿 crossed legs 二郎腿
    fetal position 曲腿至胸 leg lift 抬一只脚
    legs up 抬两只脚

Environment 环境

  • General 总体

    Environment Description Environment Description
    cityscape 城市风景 landscape 风景
    indoors 室内 outdoors 室外
  • Color/Tone 色调

    Color/Tone Description Color/Tone Description
    light 明 shade 阴凉处
    dark 暗 deep 浓
    pale 薄 grey background 背景颜色(灰)
  • Weather 天气

    Environment Description Environment Description
    golden hour lighting 黄金时段照明 in the rain 雨中
    strong rim light 强边缘光 rainy days 雨天
    night 晚上 sunset 日落
    intense shadows 强阴影 cloudy 多云
    full moon 满月 against backlight at dusk 傍晚背对阳光
  • Indoor 室内

    Environment Description Environment Description
    mirror 反射 curtains 窗帘
    on bed 床上 on floor (wooden floor) 地板上
    on carpet 在地毯上 on yoga mats 在瑜伽垫上
    chair 椅子 magic circle 魔法阵
    poker table 赌桌
  • Outdoor 室外

    Environment Description Environment Description
    mountain 山 ocean 大海
    on a hill 山上 over the sea 海边上
    the top of the hill 山顶 beautiful purple sunset at beach in the ocean 海边日落
    beautiful detailed sky, beautiful detailed water 好天好水 sunset 落日
    on the beach 海滩上 on the ocean 在大海上
    meadow 草地 plateau 高原
    desert 沙漠
  • Plant 植被

    Environment Description Environment Description
    flower 花 falling petals 落花
    petal 花瓣 cherry_blossoms 樱花
    rose 玫瑰 forest 森林/树
    rose petals 玫瑰花瓣 pink four petal flower 粉色四瓣花
  • Building 建筑

    Environment Description Environment Description
    in the baroque architecture 巴洛克建筑 in the romanesque architecture streets 罗马街道
    in the palace 宫廷 at the castle 城外为背景
    in the castle 城内为背景 in the street 在街上
    in the cyberpunk city 赛博朋克 rainy night in a cyberpunk city with glowing neon lights 赛博朋克雨天霓虹灯
    at the lighthouse 灯塔 onsen 温泉
    by the moon 月亮边 in a bar, in bars 酒吧
    in a tavern 居酒屋 Japanese arch 鸟居
    church 教堂 in a locker room 上锁房间里
    cityspace 城市风光式 power lines 电力线
    building 建筑 ruins 废墟/遗迹

References

Prompt Wiki

swiftUI笔记之Shapes实践Stacks

发表于 2023-04-16 |

基础

Circle

Circle 方法允许您绘制完美的圆形。圆形的直径等于宽度和高度之间较小的数字

1
2
3
Circle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 44, height: 44)

Ellipse

Ellipse 就像一个圆,但没有完美的纵横比 1:1。当宽度和高度不同时,它会填满空间并扭曲自己。
Ellipse()
.stroke(Color.black, lineWidth: 2)
.frame(width: 44, height: 88)

Rectangle

虽然 SwiftUI 中的大多数元素(例如 stacks 堆栈、颜色、渐变)都以矩形的形式,但它们不是形状。 Rectangle 具有 shape 属性,你可以进行描边或用作蒙版的用途。

1
2
3
Rectangle()
.foregroundColor(.blue)
.ignoresSafeArea()

RoundedRectangle

RoundedRectangle(圆角矩形) 有 cornerRadius(圆角) 和 style(样式)属性。它非常适合创建按钮、卡片,看起来更美观和圆滑。

1
2
3
4
RoundedRectangle(cornerRadius: 30, style: .continuous)
.fill(Color.green)
.frame(height: 44)
.overlay(Text("Sign up").bold())

Capsule

与 RoundedRectangle 类似,Capsule 类似胶囊的形状。胶囊的每一端都由一个半圆组成。您可以将它们用于按钮的绘制。

1
2
3
4
Capsule()
.fill(Color.green)
.frame(height: 44)
.overlay(Text("Sign up").bold())

实践

xPCQdD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import SwiftUI

struct ContentView: View {
var body: some View {
ZStack {
Rectangle()
.fill(Color.blue).ignoresSafeArea()

VStack {
Circle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 44, height: 44)
Text("Hong jun yao").foregroundColor(Color.red).bold()
Capsule()
.foregroundColor(Color.green)
.frame(height: 44)
.overlay(Text("Sign up"))
}
.padding()
.background(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 25.0, style: .continuous))
.padding()
}
.frame(width: 300.0, height: 500.0)
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
12…15

junyao

147 日志
1 标签
GitHub E-Mail 微博
© 2023 junyao 粤ICP备15028622号-5 版权所有
访客数 人 总访问量 次