SwiftUI知识

SwiftUI

闲时

Ask Apple 2022 与 SwiftUI 有关的问答(上)

Simple Swift Guide

Learn to develop beautiful iOS apps with SwiftUI

SwiftLee: A weekly blog about Swift, iOS and Xcode Tips and Tricks

SerialCoder.dev: providing educational content on iOS & macOS programming

iOS Example

Cindori Blog

Medium

Eric Callanan

SafeArea

掌握 SwiftUI 的 Safe Area

1
2
3
4
5
6
7
8
// 只扩展到底部
.ignoresSafeArea(edges: .bottom)

// 扩展到顶部和底部
.ignoresSafeArea(edges: [.bottom, .trailing])

// 横向扩展
.ignoresSafeArea(edges:.horizontal)

使用Core Data存储自定义类的数组

Store an Array of Custom Data Types in Core Data With Transformable and NSSecureCoding

【iOS】CoreData保存自定义数据(swift)

首先NSObject、NSSecureCoding

然后Transformable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 为了能让CoreData能够自己解析编码[Tag],首先上面的Tag需要先conform to:NSSexureCoding和NSObject
class TagAttributeTransformer: NSSecureUnarchiveFromDataTransformer {
override static var allowedTopLevelClasses: [AnyClass] {
[NSArray.self, Tag.self]
}

static func register() {
let className = String(describing: TagAttributeTransformer.self)
let name = NSValueTransformerName(className)
let transformer = TagAttributeTransformer()

ValueTransformer.setValueTransformer(transformer, forName: name)
}
}

Core Data Relationship in Swift 5— made simple, singer and her songs

From Hex to Color and Back in SwiftUI

有关,我在存储我的tags的时候,用的transformable存储的[Tag]数组,但是更改数组里面的一个Tag的名字或者颜色在存储的时候是无效的,原因如下,所以我后面直接用one to many这个relationship了。

Swift: How to update transformable objects

Transformable attributes are a immutable type, therefore cannot be changed. The only way of changing them is by creating a new object and saving it again to core data.

To solve this I deleted the property cartItemAttribute from my xcdatamodel which holds both a product and a quantity as one transformable attribute. I replaced it with a product attribute of type transformable and a quantity attribute of type Int and everything works fine now.

one to many之后使用自动生成的addToTags这些会有问题,所以自己写

Saving CoreData to-many relationships in Swift

Setting an NSManagedObject relationship in 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
// MARK: Generated accessors for tags
extension PersonInfo {
public var wrappedTags: [CloudTag] {
let set = tags as? Set<CloudTag> ?? []
return set.sorted {
return $0.wrappedcreatdDate < $1.wrappedcreatdDate
}
}

public func getTag(from tagID: UUID) -> CloudTag? {
return self.wrappedTags.first { $0.wrappedID == tagID}
}

// @objc(addTagsObject:)
// @NSManaged public func addToTags(_ value: CloudTag)
//
// @objc(removeTagsObject:)
// @NSManaged public func removeFromTags(_ value: CloudTag)
//
// @objc(addTags:)
// @NSManaged public func addToTags(_ values: NSSet)
//
// @objc(removeTags:)
// @NSManaged public func removeFromTags(_ values: NSSet)

func addPersonInfoTag(value: CloudTag) {
let items = self.mutableSetValue(forKey: "tags")
items.add(value)
}

func removePersonInfoTag(value: CloudTag) {
let items = self.mutableSetValue(forKey: "tags");
items.remove(value)
}
}

haptic feedback

1、2、3

UINotificationFeedbackGenerator

UIImpactFeedbackGenerator

UISelectionFeedbackGenerator

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
switch i {
case 1:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.error)

case 2:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.success)

case 3:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.warning)

case 4:
let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()

case 5:
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccurred()

case 6:
let generator = UIImpactFeedbackGenerator(style: .heavy)
generator.impactOccurred()

default:
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
i = 0
}

4、CoreHaptics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import CoreHaptics

func complexSuccess() {
// make sure that the device supports haptics
guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else { return }
var events = [CHHapticEvent]()

// create one intense, sharp tap
let intensity = CHHapticEventParameter(parameterID: .hapticIntensity, value: 1)
let sharpness = CHHapticEventParameter(parameterID: .hapticSharpness, value: 1)
let event = CHHapticEvent(eventType: .hapticTransient, parameters: [intensity, sharpness], relativeTime: 0)
events.append(event)

// convert those events into a pattern and play it immediately
do {
let pattern = try CHHapticPattern(events: events, parameters: [])
let player = try engine?.makePlayer(with: pattern)
try player?.start(atTime: 0)
} catch {
print("Failed to play pattern: \(error.localizedDescription).")
}
}

RichTextEditor

kyle-n/HighlightedTextEditor

danielsaidi/RichTextKit

cjwirth/RichEditorView

Styling List Views

Chart

Create a bar chart with SwiftUI Charts in iOS 16

官方视频

New in SwiftUI 4 : Chart Axis Configuration

jordibruin/Swift-Charts-Examples

Use SwiftUI views as points in scatter plot

Customise a line chart with SwiftUI Charts in iOS 16

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
struct ChartView9: View {

var body: some View {

let prevColor = Color(hue: 0.69, saturation: 0.19, brightness: 0.79)
let curColor = Color(hue: 0.33, saturation: 0.81, brightness: 0.76)
let curGradient = LinearGradient(
gradient: Gradient (
colors: [
curColor.opacity(0.5),
curColor.opacity(0.2),
curColor.opacity(0.05),
]
),
startPoint: .top,
endPoint: .bottom
)

VStack() {
GroupBox ( "Line Chart - Combine LIne and Area chart") {
Chart {
ForEach(previousWeek) {
LineMark(
x: .value("Week Day", $0.shortDay),
y: .value("Step Count", $0.steps)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(prevColor)
.foregroundStyle(by: .value("Week", "Previous Week"))
.lineStyle(StrokeStyle(lineWidth: 3, dash: [5, 10])) // 虚线
.symbol() {
Rectangle()
.fill(prevColor)
.frame(width: 8, height: 8)
}
.symbolSize(30)
.accessibilityLabel("\($0.weekdayString)")
.accessibilityValue("\($0.steps) Steps")
}

ForEach(currentWeek) {
LineMark(
x: .value("Week Day", $0.shortDay),
y: .value("Step Count", $0.steps)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(curColor)
.foregroundStyle(by: .value("Week", "Current Week"))
.lineStyle(StrokeStyle(lineWidth: 3))
.symbol() {
Circle()
.fill(curColor)
.frame(width: 10)
}
.symbolSize(30)
.accessibilityLabel("\($0.weekdayString)")
.accessibilityValue("\($0.steps) Steps")

// 增加区域
AreaMark(
x: .value("Week Day", $0.shortDay),
y: .value("Step Count", $0.steps)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(curGradient)
.foregroundStyle(by: .value("Week", "Current Week"))
.accessibilityLabel("\($0.weekdayString)")
.accessibilityValue("\($0.steps) Steps")

}
}
// Set the Y axis scale
.chartYScale(domain: 0...30000)

.chartForegroundStyleScale([
"Current Week" : curColor,
"Previous Week": prevColor
])
.chartLegend(position: .overlay, alignment: .top)
.chartPlotStyle { plotArea in
plotArea
.background(Color(hue: 0.12, saturation: 0.10, brightness: 0.92))
}
.chartYAxis() {
AxisMarks(position: .leading)
}
.frame(height:400)
}
.groupBoxStyle(YellowGroupBoxStyle())
Spacer()
}
.padding()
}
}

TextField

What is the @FocusState property wrapper?

Date

Is a date in same week, month, year of another date in swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
extension Date {

func isEqual(to date: Date, toGranularity component: Calendar.Component, in calendar: Calendar = .current) -> Bool {
calendar.isDate(self, equalTo: date, toGranularity: component)
}

func isInSameYear(as date: Date) -> Bool { isEqual(to: date, toGranularity: .year) }
func isInSameMonth(as date: Date) -> Bool { isEqual(to: date, toGranularity: .month) }
func isInSameWeek(as date: Date) -> Bool { isEqual(to: date, toGranularity: .weekOfYear) }

func isInSameDay(as date: Date) -> Bool { Calendar.current.isDate(self, inSameDayAs: date) }

var isInThisYear: Bool { isInSameYear(as: Date()) }
var isInThisMonth: Bool { isInSameMonth(as: Date()) }
var isInThisWeek: Bool { isInSameWeek(as: Date()) }

var isInYesterday: Bool { Calendar.current.isDateInYesterday(self) }
var isInToday: Bool { Calendar.current.isDateInToday(self) }
var isInTomorrow: Bool { Calendar.current.isDateInTomorrow(self) }

var isInTheFuture: Bool { self > Date() }
var isInThePast: Bool { self < Date() }
}

List

  • InsetListStyle - is similar to a plain list, but includes additional layout insets.

swiftui-list-style-compare

CloudKit

Sharing Core Data With CloudKit in SwiftUI

Core Data with CloudKit —— 创建与多个iCloud用户共享数据的应用

Sample-Sharing Core Data objects between iCloud users

需要将Cloud从开发模式部署到生产环境

Deploying an iCloud Container’s Schema

Picker

4 Picker styles in SwiftUI Form

A Custom Picker with SwiftUI

Working with Picker in SwiftUI

StoreKit

iOS in-app subscription tutorial with StoreKit 2 and Swift

Author: Jcwang

Permalink: http://example.com/2022/11/06/SwiftUI%E7%9F%A5%E8%AF%86/