Skip to content

Commit 9586b60

Browse files
committed
Fixed NSAttributeString race condition
+ Made some changes to the LoadingCircle element to make it look better
1 parent b6764eb commit 9586b60

File tree

6 files changed

+83
-39
lines changed

6 files changed

+83
-39
lines changed

HNReader.xcodeproj/project.pbxproj

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
C9B83DD926A863C000036AC6 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DD826A863C000036AC6 /* Job.swift */; };
2424
C9B83DDB26A863D000036AC6 /* Story.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DDA26A863D000036AC6 /* Story.swift */; };
2525
C9B83DDF26A8808900036AC6 /* CommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DDE26A8808900036AC6 /* CommentCell.swift */; };
26-
C9B83DE126A8820F00036AC6 /* HTMLText.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DE026A8820F00036AC6 /* HTMLText.swift */; };
2726
C9B83DE926A8A23C00036AC6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C9B83DE826A8A23C00036AC6 /* Assets.xcassets */; };
2827
C9B83DEB26A8A76800036AC6 /* +NSTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DEA26A8A76800036AC6 /* +NSTextField.swift */; };
28+
C9B83DED26A8ACD000036AC6 /* LoadingCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DEC26A8ACD000036AC6 /* LoadingCircle.swift */; };
29+
C9B83DEF26A8AF4A00036AC6 /* +String.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DEE26A8AF4A00036AC6 /* +String.swift */; };
2930
C9D0937726741BBE002CC786 /* HNReaderApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D0937626741BBE002CC786 /* HNReaderApp.swift */; };
3031
C9D0937926741BBE002CC786 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D0937826741BBE002CC786 /* HomeView.swift */; };
3132
C9D0937E26741BBF002CC786 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C9D0937D26741BBF002CC786 /* Preview Assets.xcassets */; };
@@ -72,9 +73,10 @@
7273
C9B83DD826A863C000036AC6 /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Job.swift; sourceTree = "<group>"; };
7374
C9B83DDA26A863D000036AC6 /* Story.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Story.swift; sourceTree = "<group>"; };
7475
C9B83DDE26A8808900036AC6 /* CommentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCell.swift; sourceTree = "<group>"; };
75-
C9B83DE026A8820F00036AC6 /* HTMLText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLText.swift; sourceTree = "<group>"; };
7676
C9B83DE826A8A23C00036AC6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
7777
C9B83DEA26A8A76800036AC6 /* +NSTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "+NSTextField.swift"; sourceTree = "<group>"; };
78+
C9B83DEC26A8ACD000036AC6 /* LoadingCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingCircle.swift; sourceTree = "<group>"; };
79+
C9B83DEE26A8AF4A00036AC6 /* +String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "+String.swift"; sourceTree = "<group>"; };
7880
C9D0937326741BBE002CC786 /* HNReader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HNReader.app; sourceTree = BUILT_PRODUCTS_DIR; };
7981
C9D0937626741BBE002CC786 /* HNReaderApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HNReaderApp.swift; sourceTree = "<group>"; };
8082
C9D0937826741BBE002CC786 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
@@ -126,6 +128,7 @@
126128
children = (
127129
3307159309D438EFAA1259C7 /* +Date.swift */,
128130
C9B83DEA26A8A76800036AC6 /* +NSTextField.swift */,
131+
C9B83DEE26A8AF4A00036AC6 /* +String.swift */,
129132
);
130133
path = Utils;
131134
sourceTree = "<group>";
@@ -160,7 +163,7 @@
160163
children = (
161164
C93F99B5267554F00046F870 /* StoryCell.swift */,
162165
C9B83DDE26A8808900036AC6 /* CommentCell.swift */,
163-
C9B83DE026A8820F00036AC6 /* HTMLText.swift */,
166+
C9B83DEC26A8ACD000036AC6 /* LoadingCircle.swift */,
164167
);
165168
path = Components;
166169
sourceTree = "<group>";
@@ -420,18 +423,19 @@
420423
C9D0938326741BBF002CC786 /* HNReader.xcdatamodeld in Sources */,
421424
C9E9BD032674D095001B4E19 /* User.swift in Sources */,
422425
C9E9BCFF2674CB6C001B4E19 /* HackerNewsClient.swift in Sources */,
426+
C9B83DEF26A8AF4A00036AC6 /* +String.swift in Sources */,
423427
C9E9BD012674D007001B4E19 /* HackerNews.swift in Sources */,
424428
C9D0937726741BBE002CC786 /* HNReaderApp.swift in Sources */,
425429
330713D3016ED410AFD53FDF /* ItemListViewModel.swift in Sources */,
426430
C9B83DDB26A863D000036AC6 /* Story.swift in Sources */,
427431
330711A9216E762026AF98A0 /* +Date.swift in Sources */,
428432
C9B58794267C153C005E0A50 /* DetailStoryView.swift in Sources */,
429433
C9B83DD426A8631300036AC6 /* Comment.swift in Sources */,
430-
C9B83DE126A8820F00036AC6 /* HTMLText.swift in Sources */,
431434
33071F1C64D4742E1F947FAA /* ItemDownloader.swift in Sources */,
432435
3307147AB95F03650FC40B97 /* ItemCache.swift in Sources */,
433436
C9B83DD926A863C000036AC6 /* Job.swift in Sources */,
434437
C9B83DDF26A8808900036AC6 /* CommentCell.swift in Sources */,
438+
C9B83DED26A8ACD000036AC6 /* LoadingCircle.swift in Sources */,
435439
);
436440
runOnlyForDeploymentPostprocessing = 0;
437441
};

HNReader/Utils/+String.swift

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// +String.swift
3+
// HNReader
4+
//
5+
// Created by Mattia Righetti on 21/07/21.
6+
//
7+
8+
import Foundation
9+
10+
extension String {
11+
init?(htmlEncodedString: String) {
12+
guard let data = htmlEncodedString.data(using: .utf8) else {
13+
return nil
14+
}
15+
16+
let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
17+
.documentType: NSAttributedString.DocumentType.html,
18+
.characterEncoding: String.Encoding.utf8.rawValue
19+
]
20+
21+
guard let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) else {
22+
return nil
23+
}
24+
25+
self.init(attributedString.string)
26+
}
27+
}

HNReader/View/Components/CommentCell.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct CommentCell: View {
1818
.foregroundColor(.yellow)
1919

2020
HStack {
21-
HTMLText(text: comment.text ?? "Empty comment")
21+
Text(comment.text!)
2222
Spacer()
2323
}
2424
}

HNReader/View/Components/HTMLText.swift

-33
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// LoadingCircle.swift
3+
// HNReader
4+
//
5+
// Created by Mattia Righetti on 21/07/21.
6+
//
7+
8+
import SwiftUI
9+
10+
struct LoadingCircle: View {
11+
@State private var isLoading = false
12+
13+
var body: some View {
14+
ZStack {
15+
Circle()
16+
.stroke(Color.gray.opacity(0.5), lineWidth: 10)
17+
.frame(width: 50, height: 50)
18+
19+
Circle()
20+
.trim(from: 0, to: 0.2)
21+
.stroke(Color.green.opacity(0.7), style: .init(lineWidth: 7, lineCap: .round))
22+
.frame(width: 50, height: 50)
23+
.rotationEffect(Angle(degrees: isLoading ? 360 : 0))
24+
.animation(
25+
Animation
26+
.linear(duration: 1)
27+
.repeatForever(autoreverses: false)
28+
)
29+
.onAppear() {
30+
self.isLoading = true
31+
}
32+
}
33+
.frame(width: 70, height: 70)
34+
}
35+
}
36+
37+
struct LoadingCircle_Previews: PreviewProvider {
38+
static var previews: some View {
39+
LoadingCircle()
40+
}
41+
}

HNReader/View/DetailStoryView.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct DetailStoryView: View {
6060
@ViewBuilder
6161
func CommentsSection() -> some View {
6262
if fetching {
63-
Text("Fetching")
63+
LoadingCircle()
6464
} else {
6565
if let comments = comments {
6666
VStack(alignment: .leading) {
@@ -92,6 +92,11 @@ struct DetailStoryView: View {
9292

9393
DispatchQueue.main.async {
9494
self.comments = flattenComments.compactMap { $0 } as? [Comment]
95+
if let comments = self.comments {
96+
for comment in comments {
97+
comment.text = String(htmlEncodedString: comment.text ?? "Empty comment")
98+
}
99+
}
95100
self.fetching = false
96101
}
97102
}

0 commit comments

Comments
 (0)