Skip to content

Commit

Permalink
格式化内容
Browse files Browse the repository at this point in the history
  • Loading branch information
ming1016 committed May 29, 2024
1 parent bcc226f commit dcda8c9
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 1 deletion.
24 changes: 24 additions & 0 deletions SwiftPamphletApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
08069CAB2BDE01E800D48E24 /* GuideListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08069CAA2BDE01E800D48E24 /* GuideListView.swift */; };
08069CAD2BDE7A6B00D48E24 /* GuideDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08069CAC2BDE7A6B00D48E24 /* GuideDetailView.swift */; };
0820367A2C02EEA7002FB5E3 /* SMUI in Frameworks */ = {isa = PBXBuildFile; productRef = 082036792C02EEA7002FB5E3 /* SMUI */; };
082036802C073C0E002FB5E3 /* 格式化-时间(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 0820367F2C073C0E002FB5E3 /* 格式化-时间(ap).md */; };
082036822C073C24002FB5E3 /* 格式化-数据(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 082036812C073C24002FB5E3 /* 格式化-数据(ap).md */; };
082036842C075A01002FB5E3 /* 格式化-度量值(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 082036832C075A01002FB5E3 /* 格式化-度量值(ap).md */; };
082036862C075A18002FB5E3 /* 格式化-生活日常(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 082036852C075A18002FB5E3 /* 格式化-生活日常(ap).md */; };
0825E4872BC6596F00332378 /* EditCustomSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0825E4862BC6596F00332378 /* EditCustomSearchView.swift */; };
08397E252B9EEE1300DFDD02 /* InfoListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08397E242B9EEE1300DFDD02 /* InfoListView.swift */; };
08397E292B9F0A9100DFDD02 /* EditInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08397E282B9F0A9100DFDD02 /* EditInfoView.swift */; };
Expand Down Expand Up @@ -356,6 +360,10 @@
08026C502869B41B00792EF1 /* Table(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Table(ap).md"; sourceTree = "<group>"; };
08069CAA2BDE01E800D48E24 /* GuideListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideListView.swift; sourceTree = "<group>"; };
08069CAC2BDE7A6B00D48E24 /* GuideDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideDetailView.swift; sourceTree = "<group>"; };
0820367F2C073C0E002FB5E3 /* 格式化-时间(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-时间(ap).md"; sourceTree = "<group>"; };
082036812C073C24002FB5E3 /* 格式化-数据(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-数据(ap).md"; sourceTree = "<group>"; };
082036832C075A01002FB5E3 /* 格式化-度量值(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-度量值(ap).md"; sourceTree = "<group>"; };
082036852C075A18002FB5E3 /* 格式化-生活日常(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "格式化-生活日常(ap).md"; sourceTree = "<group>"; };
0825E4862BC6596F00332378 /* EditCustomSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditCustomSearchView.swift; sourceTree = "<group>"; };
08397E242B9EEE1300DFDD02 /* InfoListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoListView.swift; sourceTree = "<group>"; };
08397E282B9F0A9100DFDD02 /* EditInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -700,6 +708,17 @@
path = "性能和构建";
sourceTree = "<group>";
};
0820367E2C073BF8002FB5E3 /* 格式化 */ = {
isa = PBXGroup;
children = (
0820367F2C073C0E002FB5E3 /* 格式化-时间(ap).md */,
082036812C073C24002FB5E3 /* 格式化-数据(ap).md */,
082036832C075A01002FB5E3 /* 格式化-度量值(ap).md */,
082036852C075A18002FB5E3 /* 格式化-生活日常(ap).md */,
);
path = "格式化";
sourceTree = "<group>";
};
08397E212B9EE83F00DFDD02 /* InfoOrganizer */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -795,6 +814,7 @@
0850445227B110A50096D556 /* 自带协议 */,
08448F69279EB47E00B61353 /* 时间(ap).md */,
08448F6C279EB51000B61353 /* 格式化(ap).md */,
0820367E2C073BF8002FB5E3 /* 格式化 */,
08448F6E279EB56400B61353 /* 度量值(ap).md */,
08448F70279EB58C00B61353 /* Data(ap).md */,
08448F72279EB5DF00B61353 /* 文件(ap).md */,
Expand Down Expand Up @@ -1748,6 +1768,7 @@
087ECE4F2C01B7280011F679 /* Matched Geometry Effect(ap).md in Resources */,
08448F9A279EBA2900B61353 /* 可选(ap).md in Resources */,
08026C472869B26900792EF1 /* 调试(ap).md in Resources */,
082036842C075A01002FB5E3 /* 格式化-度量值(ap).md in Resources */,
08448F8C279EB84800B61353 /* 布局动画(ap).md in Resources */,
08448FC1279EC4B500B61353 /* filter(ap).md in Resources */,
086BEEFC2BF63A0000025307 /* Layout协议(ap).md in Resources */,
Expand Down Expand Up @@ -1843,6 +1864,7 @@
087ECE042BFCC3AA0011F679 /* Popover(ap).md in Resources */,
086923382BF19AB7006779A3 /* scrollTargetBehavior分页滚动(ap).md in Resources */,
08448FAB279EC2B400B61353 /* 枚举(ap).md in Resources */,
082036802C073C0E002FB5E3 /* 格式化-时间(ap).md in Resources */,
08522BD627CF3218005FF059 /* Picker(ap).md in Resources */,
08659BD92BE9A80E009B7C00 /* SwiftData多线程(ap).md in Resources */,
08448FCE279EC5AA00B61353 /* While(ap).md in Resources */,
Expand Down Expand Up @@ -1920,6 +1942,7 @@
087ECE2B2BFF25D30011F679 /* Shapes协议(ap).md in Resources */,
08448F6D279EB51000B61353 /* 格式化(ap).md in Resources */,
08448FF4279EC9C500B61353 /* publisher(ap).md in Resources */,
082036862C075A18002FB5E3 /* 格式化-生活日常(ap).md in Resources */,
08448FBC279EC41700B61353 /* 继承(ap).md in Resources */,
0850444C27B0D1F80096D556 /* canImport判断库是否可使用(ap).md in Resources */,
08448F59279EA84100B61353 /* macOS范例(ap).md in Resources */,
Expand Down Expand Up @@ -1948,6 +1971,7 @@
08449030279ECF7D00B61353 /* 1.md in Resources */,
087ECE352BFF26620011F679 /* Responder chain协议(ap).md in Resources */,
087ECE3D2BFF491B0011F679 /* SwiftUI-Shadow(ap).md in Resources */,
082036822C073C24002FB5E3 /* 格式化-数据(ap).md in Resources */,
08522BDA27CF5029005FF059 /* Slider(ap).md in Resources */,
08D8EFFA2BEF9C9800AA0020 /* 小组件-远程定时获取数据(ap).md in Resources */,
0850AC102BF30058009FDBBF /* List-完全可点击的行(ap).md in Resources */,
Expand Down
7 changes: 6 additions & 1 deletion SwiftPamphletApp/Guide/View/GuideListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,12 @@ final class GuideListModel {
L(t: "JSON没有id字段")
]),
L(t: "时间"),
L(t: "格式化"),
L(t: "格式化", sub: [
L(t: "格式化-时间"),
L(t: "格式化-数据"),
L(t: "格式化-度量值"),
L(t: "格式化-生活日常"),
]),
L(t: "度量值"),
L(t: "Data"),
L(t: "文件"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@


MeasurementFormatter

使用 Swift Foundation Formatter API
```swift
Measurement<UnitMass>(value: 1, unit: .kilograms)
.formatted(.measurement(width: .abbreviated))
```

标准库里的物理量,在这个文档里有详细列出,包括角度、平方米等。
```swift
// 参考:https://developer.apple.com/documentation/foundation/nsdimension
let m1 = Measurement(value: 1, unit: UnitLength.kilometers)
let m2 = m1.converted(to: .meters) // 千米转米
print(m2) // 1000.0 m
// 度量值转为本地化的值
let mf = MeasurementFormatter()
mf.locale = Locale(identifier: "zh_Hans_CN")
print(mf.string(from: m1)) // 1公里
```

一些物理公式供参考:
```
面积 = 长度 × 长度
体积 = 长度 × 长度 × 长度 = 面积 × 长度
速度=长度/时间
加速度=速度/时间
力 = 质量 × 加速度
扭矩 = 力 × 长度
压力 = 力 / 面积
密度=质量 / 体积
能量 = 功率 × 时间
电阻 = 电压 / 电流
```


描述多个事物
```swift
// 描述多个事物
let s1 = ListFormatter.localizedString(byJoining: ["冬天","春天","夏天","秋天"])
print(s1)
```

使用 Foundation Formatter API
```swift
["足球", "篮球"].formatted(.list(type: .and))
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@


## `.formatted`

```swift
print(888.formatted(.currency(code: "RMB")))
print(99999.formatted())
print(0.3.formatted(.percent))
print(3.14.formatted(.number.precision(.fractionLength(1))))
```

## NumberFormatter 描述数字

```swift
// 数字
let f3 = NumberFormatter()
f3.locale = Locale(identifier: "zh_Hans_CN")
f3.numberStyle = .currency
print(f3.string(from: 123456) ?? "") // ¥123,456.00
f3.numberStyle = .percent
print(f3.string(from: 123456) ?? "") // 12,345,600%

let n1 = 1.23456
let n1Str = n1.formatted(.number.precision(.fractionLength(3)).rounded())
print(n1Str) // 1.235
```

ByteCountFormatter 描述数据大小
```swift
let formatter = ByteCountFormatter()
formatter.countStyle = .file

text = formatter.string(fromByteCount: 1_000_000_000) // 1GB
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@

## 格式化时间成字符串

格式化日期的示例。这些方法都是在 `Date` 类型上调用的,它们返回一个格式化的字符串,表示当前日期和时间。

```swift
Date.now.formatted()
```
这行代码返回一个默认格式的日期和时间字符串。

```swift
Date.now.formatted(.relative(presentation: .named))
```
这行代码返回一个相对于现在的时间字符串,例如 "5 分钟前" 或 "明天"。

```swift
Date.now.formatted(date: .abbreviated, time: .omitted)
```
这行代码返回一个简写的日期字符串,不包含时间。

```swift
Date.now.formatted(.dateTime.day(.twoDigits).month(.abbreviated).year(.twoDigits))
```
这行代码返回一个自定义格式的日期和时间字符串,包含两位数的日、简写的月和两位数的年。

```swift
Date.now.formatted(.iso8601)
```
这行代码返回一个 ISO 8601 格式的日期和时间字符串。

代码示例:

```swift
struct Movie {
let title: String
let screeningDates: [Date]
}

let movie = Movie(title: "电影标题", screeningDates: [Date.now, Date.now.advanced(by: 60*60*24)])

for date in movie.screeningDates {
print("\(movie.title) 的放映时间是 \(date.formatted(date: .abbreviated, time: .shortened))")
}
```

这段代码会打印出电影的标题和每个放映时间,时间是以简写的日期和短格式的时间显示的。


## 相对时间差

描述两个日期之间的相对时间差。这个类可以生成如 "昨天"、"5 分钟前" 这样的字符串。

```swift
let d1 = Date().timeIntervalSince1970 - 60 * 60 * 24
```
这行代码创建了一个 `Date` 对象,表示当前时间减去 24 小时(即一天前的时间)。

```swift
let f1 = RelativeDateTimeFormatter()
f1.dateTimeStyle = .named
f1.formattingContext = .beginningOfSentence
f1.locale = Locale(identifier: "zh_Hans_CN")
let str = f1.localizedString(for: Date(timeIntervalSince1970: d1), relativeTo: Date())
print(str) // 昨天
```
这些代码创建了一个 `RelativeDateTimeFormatter` 对象,并设置了其样式和语言环境。然后,它使用这个格式化器来生成一个表示 `d1` 和当前时间相对时间差的字符串。

```swift
let str2 = Date.now.addingTimeInterval(-(60 * 60 * 24))
.formatted(.relative(presentation: .named))
print(str2) // yesterday
```
这行代码做的事情和前面的代码类似,但是它使用了 Swift 5.5 引入的新的 `Date` 格式化 API。这个 API 更简洁,更易于使用。

我们可能会有一个电影放映时间的列表,我们可以使用这些方法来描述每个放映时间距离现在有多久。例如:

```swift
struct Movie {
let title: String
let screeningDates: [Date]
}

let movie = Movie(title: "电影标题", screeningDates: [Date.now, Date.now.advanced(by: 60*60*24)])

for date in movie.screeningDates {
let relativeTime = date.formatted(.relative(presentation: .named))
print("\(movie.title) 的放映时间是 \(relativeTime)")
}
```

这段代码会打印出电影的标题和每个放映时间距离现在的相对时间。


## 剩余时间

描述一个时间间隔。这个类可以生成如 "大约 5 分钟" 这样的字符串。

电影的剩余播放时间,我们可以使用这个方法来描述这个时间。例如:

```swift
struct Movie {
let title: String
let remainingTime: TimeInterval
}

let movie = Movie(title: "电影标题", remainingTime: 300.0)

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.includesApproximationPhrase = true
formatter.includesTimeRemainingPhrase = true
let text = formatter.string(from: movie.remainingTime) ?? ""

print("\(movie.title) 的剩余播放时间是 \(text)")
```

这段代码会打印出电影的标题和剩余播放时间。


## DateIntervalFormatter

一个电影的放映时间段,我们可以使用这个方法来描述这个时间段。例如:

```swift
struct Movie {
let title: String
let screeningInterval: (start: Date, end: Date)
}

let movie = Movie(title: "电影标题", screeningInterval: (start: Date(), end: Date(timeInterval: 86400, since: Date())))

let formatter = DateIntervalFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .none
let text = formatter.string(from: movie.screeningInterval.start, to: movie.screeningInterval.end)

print("\(movie.title) 的放映时间段是 \(text)")
```

这段代码会打印出电影的标题和放映时间段。
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

描述人名
```swift
// 名字
let f2 = PersonNameComponentsFormatter()
var nc1 = PersonNameComponents()
nc1.familyName = ""
nc1.givenName = ""
nc1.nickname = "铭哥"
print(f2.string(from: nc1)) // 戴铭
f2.style = .short
print(f2.string(from: nc1)) // 铭哥
f2.style = .abbreviated
print(f2.string(from: nc1)) //

var nc2 = PersonNameComponents()
nc2.familyName = "Dai"
nc2.givenName = "Ming"
nc2.nickname = "Starming"
f2.style = .default
print(f2.string(from: nc2)) // Ming Dai
f2.style = .short
print(f2.string(from: nc2)) // Starming
f2.style = .abbreviated
print(f2.string(from: nc2)) // MD

// 取出名
let componets = f2.personNameComponents(from: "戴铭")
print(componets?.givenName ?? "") //
```

描述地址
```swift
// 地址
import Contacts

let f4 = CNPostalAddressFormatter()
let address = CNMutablePostalAddress()
address.street = "海淀区王庄路XX号院X号楼X门XXX"
address.postalCode = "100083"
address.city = "北京"
address.country = "中国"
print(f4.string(from: address))
/// 海淀区王庄路XX号院X号楼X门XXX
/// 北京 100083
/// 中国
```

0 comments on commit dcda8c9

Please sign in to comment.