Skip to content

Commit dcda8c9

Browse files
committed
格式化内容
1 parent bcc226f commit dcda8c9

File tree

6 files changed

+302
-1
lines changed

6 files changed

+302
-1
lines changed

SwiftPamphletApp.xcodeproj/project.pbxproj

+24
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
08069CAB2BDE01E800D48E24 /* GuideListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08069CAA2BDE01E800D48E24 /* GuideListView.swift */; };
2828
08069CAD2BDE7A6B00D48E24 /* GuideDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08069CAC2BDE7A6B00D48E24 /* GuideDetailView.swift */; };
2929
0820367A2C02EEA7002FB5E3 /* SMUI in Frameworks */ = {isa = PBXBuildFile; productRef = 082036792C02EEA7002FB5E3 /* SMUI */; };
30+
082036802C073C0E002FB5E3 /* 格式化-时间(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 0820367F2C073C0E002FB5E3 /* 格式化-时间(ap).md */; };
31+
082036822C073C24002FB5E3 /* 格式化-数据(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 082036812C073C24002FB5E3 /* 格式化-数据(ap).md */; };
32+
082036842C075A01002FB5E3 /* 格式化-度量值(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 082036832C075A01002FB5E3 /* 格式化-度量值(ap).md */; };
33+
082036862C075A18002FB5E3 /* 格式化-生活日常(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 082036852C075A18002FB5E3 /* 格式化-生活日常(ap).md */; };
3034
0825E4872BC6596F00332378 /* EditCustomSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0825E4862BC6596F00332378 /* EditCustomSearchView.swift */; };
3135
08397E252B9EEE1300DFDD02 /* InfoListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08397E242B9EEE1300DFDD02 /* InfoListView.swift */; };
3236
08397E292B9F0A9100DFDD02 /* EditInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08397E282B9F0A9100DFDD02 /* EditInfoView.swift */; };
@@ -356,6 +360,10 @@
356360
08026C502869B41B00792EF1 /* Table(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Table(ap).md"; sourceTree = "<group>"; };
357361
08069CAA2BDE01E800D48E24 /* GuideListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideListView.swift; sourceTree = "<group>"; };
358362
08069CAC2BDE7A6B00D48E24 /* GuideDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideDetailView.swift; sourceTree = "<group>"; };
363+
0820367F2C073C0E002FB5E3 /* 格式化-时间(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-时间(ap).md"; sourceTree = "<group>"; };
364+
082036812C073C24002FB5E3 /* 格式化-数据(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-数据(ap).md"; sourceTree = "<group>"; };
365+
082036832C075A01002FB5E3 /* 格式化-度量值(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-度量值(ap).md"; sourceTree = "<group>"; };
366+
082036852C075A18002FB5E3 /* 格式化-生活日常(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-生活日常(ap).md"; sourceTree = "<group>"; };
359367
0825E4862BC6596F00332378 /* EditCustomSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditCustomSearchView.swift; sourceTree = "<group>"; };
360368
08397E242B9EEE1300DFDD02 /* InfoListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoListView.swift; sourceTree = "<group>"; };
361369
08397E282B9F0A9100DFDD02 /* EditInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoView.swift; sourceTree = "<group>"; };
@@ -700,6 +708,17 @@
700708
path = "性能和构建";
701709
sourceTree = "<group>";
702710
};
711+
0820367E2C073BF8002FB5E3 /* 格式化 */ = {
712+
isa = PBXGroup;
713+
children = (
714+
0820367F2C073C0E002FB5E3 /* 格式化-时间(ap).md */,
715+
082036812C073C24002FB5E3 /* 格式化-数据(ap).md */,
716+
082036832C075A01002FB5E3 /* 格式化-度量值(ap).md */,
717+
082036852C075A18002FB5E3 /* 格式化-生活日常(ap).md */,
718+
);
719+
path = "格式化";
720+
sourceTree = "<group>";
721+
};
703722
08397E212B9EE83F00DFDD02 /* InfoOrganizer */ = {
704723
isa = PBXGroup;
705724
children = (
@@ -795,6 +814,7 @@
795814
0850445227B110A50096D556 /* 自带协议 */,
796815
08448F69279EB47E00B61353 /* 时间(ap).md */,
797816
08448F6C279EB51000B61353 /* 格式化(ap).md */,
817+
0820367E2C073BF8002FB5E3 /* 格式化 */,
798818
08448F6E279EB56400B61353 /* 度量值(ap).md */,
799819
08448F70279EB58C00B61353 /* Data(ap).md */,
800820
08448F72279EB5DF00B61353 /* 文件(ap).md */,
@@ -1748,6 +1768,7 @@
17481768
087ECE4F2C01B7280011F679 /* Matched Geometry Effect(ap).md in Resources */,
17491769
08448F9A279EBA2900B61353 /* 可选(ap).md in Resources */,
17501770
08026C472869B26900792EF1 /* 调试(ap).md in Resources */,
1771+
082036842C075A01002FB5E3 /* 格式化-度量值(ap).md in Resources */,
17511772
08448F8C279EB84800B61353 /* 布局动画(ap).md in Resources */,
17521773
08448FC1279EC4B500B61353 /* filter(ap).md in Resources */,
17531774
086BEEFC2BF63A0000025307 /* Layout协议(ap).md in Resources */,
@@ -1843,6 +1864,7 @@
18431864
087ECE042BFCC3AA0011F679 /* Popover(ap).md in Resources */,
18441865
086923382BF19AB7006779A3 /* scrollTargetBehavior分页滚动(ap).md in Resources */,
18451866
08448FAB279EC2B400B61353 /* 枚举(ap).md in Resources */,
1867+
082036802C073C0E002FB5E3 /* 格式化-时间(ap).md in Resources */,
18461868
08522BD627CF3218005FF059 /* Picker(ap).md in Resources */,
18471869
08659BD92BE9A80E009B7C00 /* SwiftData多线程(ap).md in Resources */,
18481870
08448FCE279EC5AA00B61353 /* While(ap).md in Resources */,
@@ -1920,6 +1942,7 @@
19201942
087ECE2B2BFF25D30011F679 /* Shapes协议(ap).md in Resources */,
19211943
08448F6D279EB51000B61353 /* 格式化(ap).md in Resources */,
19221944
08448FF4279EC9C500B61353 /* publisher(ap).md in Resources */,
1945+
082036862C075A18002FB5E3 /* 格式化-生活日常(ap).md in Resources */,
19231946
08448FBC279EC41700B61353 /* 继承(ap).md in Resources */,
19241947
0850444C27B0D1F80096D556 /* canImport判断库是否可使用(ap).md in Resources */,
19251948
08448F59279EA84100B61353 /* macOS范例(ap).md in Resources */,
@@ -1948,6 +1971,7 @@
19481971
08449030279ECF7D00B61353 /* 1.md in Resources */,
19491972
087ECE352BFF26620011F679 /* Responder chain协议(ap).md in Resources */,
19501973
087ECE3D2BFF491B0011F679 /* SwiftUI-Shadow(ap).md in Resources */,
1974+
082036822C073C24002FB5E3 /* 格式化-数据(ap).md in Resources */,
19511975
08522BDA27CF5029005FF059 /* Slider(ap).md in Resources */,
19521976
08D8EFFA2BEF9C9800AA0020 /* 小组件-远程定时获取数据(ap).md in Resources */,
19531977
0850AC102BF30058009FDBBF /* List-完全可点击的行(ap).md in Resources */,

SwiftPamphletApp/Guide/View/GuideListView.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,12 @@ final class GuideListModel {
234234
L(t: "JSON没有id字段")
235235
]),
236236
L(t: "时间"),
237-
L(t: "格式化"),
237+
L(t: "格式化", sub: [
238+
L(t: "格式化-时间"),
239+
L(t: "格式化-数据"),
240+
L(t: "格式化-度量值"),
241+
L(t: "格式化-生活日常"),
242+
]),
238243
L(t: "度量值"),
239244
L(t: "Data"),
240245
L(t: "文件"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
3+
MeasurementFormatter
4+
5+
使用 Swift Foundation Formatter API
6+
```swift
7+
Measurement<UnitMass>(value: 1, unit: .kilograms)
8+
.formatted(.measurement(width: .abbreviated))
9+
```
10+
11+
标准库里的物理量,在这个文档里有详细列出,包括角度、平方米等。
12+
```swift
13+
// 参考:https://developer.apple.com/documentation/foundation/nsdimension
14+
let m1 = Measurement(value: 1, unit: UnitLength.kilometers)
15+
let m2 = m1.converted(to: .meters) // 千米转米
16+
print(m2) // 1000.0 m
17+
// 度量值转为本地化的值
18+
let mf = MeasurementFormatter()
19+
mf.locale = Locale(identifier: "zh_Hans_CN")
20+
print(mf.string(from: m1)) // 1公里
21+
```
22+
23+
一些物理公式供参考:
24+
```
25+
面积 = 长度 × 长度
26+
体积 = 长度 × 长度 × 长度 = 面积 × 长度
27+
28+
速度=长度/时间
29+
加速度=速度/时间
30+
31+
力 = 质量 × 加速度
32+
扭矩 = 力 × 长度
33+
压力 = 力 / 面积
34+
35+
密度=质量 / 体积
36+
能量 = 功率 × 时间
37+
电阻 = 电压 / 电流
38+
```
39+
40+
41+
描述多个事物
42+
```swift
43+
// 描述多个事物
44+
let s1 = ListFormatter.localizedString(byJoining: ["冬天","春天","夏天","秋天"])
45+
print(s1)
46+
```
47+
48+
使用 Foundation Formatter API
49+
```swift
50+
["足球", "篮球"].formatted(.list(type: .and))
51+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
3+
## `.formatted`
4+
5+
```swift
6+
print(888.formatted(.currency(code: "RMB")))
7+
print(99999.formatted())
8+
print(0.3.formatted(.percent))
9+
print(3.14.formatted(.number.precision(.fractionLength(1))))
10+
```
11+
12+
## NumberFormatter 描述数字
13+
14+
```swift
15+
// 数字
16+
let f3 = NumberFormatter()
17+
f3.locale = Locale(identifier: "zh_Hans_CN")
18+
f3.numberStyle = .currency
19+
print(f3.string(from: 123456) ?? "") // ¥123,456.00
20+
f3.numberStyle = .percent
21+
print(f3.string(from: 123456) ?? "") // 12,345,600%
22+
23+
let n1 = 1.23456
24+
let n1Str = n1.formatted(.number.precision(.fractionLength(3)).rounded())
25+
print(n1Str) // 1.235
26+
```
27+
28+
ByteCountFormatter 描述数据大小
29+
```swift
30+
let formatter = ByteCountFormatter()
31+
formatter.countStyle = .file
32+
33+
text = formatter.string(fromByteCount: 1_000_000_000) // 1GB
34+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
2+
## 格式化时间成字符串
3+
4+
格式化日期的示例。这些方法都是在 `Date` 类型上调用的,它们返回一个格式化的字符串,表示当前日期和时间。
5+
6+
```swift
7+
Date.now.formatted()
8+
```
9+
这行代码返回一个默认格式的日期和时间字符串。
10+
11+
```swift
12+
Date.now.formatted(.relative(presentation: .named))
13+
```
14+
这行代码返回一个相对于现在的时间字符串,例如 "5 分钟前" 或 "明天"。
15+
16+
```swift
17+
Date.now.formatted(date: .abbreviated, time: .omitted)
18+
```
19+
这行代码返回一个简写的日期字符串,不包含时间。
20+
21+
```swift
22+
Date.now.formatted(.dateTime.day(.twoDigits).month(.abbreviated).year(.twoDigits))
23+
```
24+
这行代码返回一个自定义格式的日期和时间字符串,包含两位数的日、简写的月和两位数的年。
25+
26+
```swift
27+
Date.now.formatted(.iso8601)
28+
```
29+
这行代码返回一个 ISO 8601 格式的日期和时间字符串。
30+
31+
代码示例:
32+
33+
```swift
34+
struct Movie {
35+
let title: String
36+
let screeningDates: [Date]
37+
}
38+
39+
let movie = Movie(title: "电影标题", screeningDates: [Date.now, Date.now.advanced(by: 60*60*24)])
40+
41+
for date in movie.screeningDates {
42+
print("\(movie.title) 的放映时间是 \(date.formatted(date: .abbreviated, time: .shortened))")
43+
}
44+
```
45+
46+
这段代码会打印出电影的标题和每个放映时间,时间是以简写的日期和短格式的时间显示的。
47+
48+
49+
## 相对时间差
50+
51+
描述两个日期之间的相对时间差。这个类可以生成如 "昨天"、"5 分钟前" 这样的字符串。
52+
53+
```swift
54+
let d1 = Date().timeIntervalSince1970 - 60 * 60 * 24
55+
```
56+
这行代码创建了一个 `Date` 对象,表示当前时间减去 24 小时(即一天前的时间)。
57+
58+
```swift
59+
let f1 = RelativeDateTimeFormatter()
60+
f1.dateTimeStyle = .named
61+
f1.formattingContext = .beginningOfSentence
62+
f1.locale = Locale(identifier: "zh_Hans_CN")
63+
let str = f1.localizedString(for: Date(timeIntervalSince1970: d1), relativeTo: Date())
64+
print(str) // 昨天
65+
```
66+
这些代码创建了一个 `RelativeDateTimeFormatter` 对象,并设置了其样式和语言环境。然后,它使用这个格式化器来生成一个表示 `d1` 和当前时间相对时间差的字符串。
67+
68+
```swift
69+
let str2 = Date.now.addingTimeInterval(-(60 * 60 * 24))
70+
.formatted(.relative(presentation: .named))
71+
print(str2) // yesterday
72+
```
73+
这行代码做的事情和前面的代码类似,但是它使用了 Swift 5.5 引入的新的 `Date` 格式化 API。这个 API 更简洁,更易于使用。
74+
75+
我们可能会有一个电影放映时间的列表,我们可以使用这些方法来描述每个放映时间距离现在有多久。例如:
76+
77+
```swift
78+
struct Movie {
79+
let title: String
80+
let screeningDates: [Date]
81+
}
82+
83+
let movie = Movie(title: "电影标题", screeningDates: [Date.now, Date.now.advanced(by: 60*60*24)])
84+
85+
for date in movie.screeningDates {
86+
let relativeTime = date.formatted(.relative(presentation: .named))
87+
print("\(movie.title) 的放映时间是 \(relativeTime)")
88+
}
89+
```
90+
91+
这段代码会打印出电影的标题和每个放映时间距离现在的相对时间。
92+
93+
94+
## 剩余时间
95+
96+
描述一个时间间隔。这个类可以生成如 "大约 5 分钟" 这样的字符串。
97+
98+
电影的剩余播放时间,我们可以使用这个方法来描述这个时间。例如:
99+
100+
```swift
101+
struct Movie {
102+
let title: String
103+
let remainingTime: TimeInterval
104+
}
105+
106+
let movie = Movie(title: "电影标题", remainingTime: 300.0)
107+
108+
let formatter = DateComponentsFormatter()
109+
formatter.unitsStyle = .full
110+
formatter.includesApproximationPhrase = true
111+
formatter.includesTimeRemainingPhrase = true
112+
let text = formatter.string(from: movie.remainingTime) ?? ""
113+
114+
print("\(movie.title) 的剩余播放时间是 \(text)")
115+
```
116+
117+
这段代码会打印出电影的标题和剩余播放时间。
118+
119+
120+
## DateIntervalFormatter
121+
122+
一个电影的放映时间段,我们可以使用这个方法来描述这个时间段。例如:
123+
124+
```swift
125+
struct Movie {
126+
let title: String
127+
let screeningInterval: (start: Date, end: Date)
128+
}
129+
130+
let movie = Movie(title: "电影标题", screeningInterval: (start: Date(), end: Date(timeInterval: 86400, since: Date())))
131+
132+
let formatter = DateIntervalFormatter()
133+
formatter.dateStyle = .short
134+
formatter.timeStyle = .none
135+
let text = formatter.string(from: movie.screeningInterval.start, to: movie.screeningInterval.end)
136+
137+
print("\(movie.title) 的放映时间段是 \(text)")
138+
```
139+
140+
这段代码会打印出电影的标题和放映时间段。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
描述人名
3+
```swift
4+
// 名字
5+
let f2 = PersonNameComponentsFormatter()
6+
var nc1 = PersonNameComponents()
7+
nc1.familyName = ""
8+
nc1.givenName = ""
9+
nc1.nickname = "铭哥"
10+
print(f2.string(from: nc1)) // 戴铭
11+
f2.style = .short
12+
print(f2.string(from: nc1)) // 铭哥
13+
f2.style = .abbreviated
14+
print(f2.string(from: nc1)) //
15+
16+
var nc2 = PersonNameComponents()
17+
nc2.familyName = "Dai"
18+
nc2.givenName = "Ming"
19+
nc2.nickname = "Starming"
20+
f2.style = .default
21+
print(f2.string(from: nc2)) // Ming Dai
22+
f2.style = .short
23+
print(f2.string(from: nc2)) // Starming
24+
f2.style = .abbreviated
25+
print(f2.string(from: nc2)) // MD
26+
27+
// 取出名
28+
let componets = f2.personNameComponents(from: "戴铭")
29+
print(componets?.givenName ?? "") //
30+
```
31+
32+
描述地址
33+
```swift
34+
// 地址
35+
import Contacts
36+
37+
let f4 = CNPostalAddressFormatter()
38+
let address = CNMutablePostalAddress()
39+
address.street = "海淀区王庄路XX号院X号楼X门XXX"
40+
address.postalCode = "100083"
41+
address.city = "北京"
42+
address.country = "中国"
43+
print(f4.string(from: address))
44+
/// 海淀区王庄路XX号院X号楼X门XXX
45+
/// 北京 100083
46+
/// 中国
47+
```

0 commit comments

Comments
 (0)