Skip to content

Commit aa4119c

Browse files
authored
Add nullability annotations to ReaderPost (#25039)
* Add nullability annotations to ReaderPost * Adapt the ReaderPost nullability annotations * Fix unit tests compilation issues * Add wpAssert statements
1 parent 0dbd06c commit aa4119c

19 files changed

+106
-81
lines changed

Sources/WordPressData/Objective-C/include/ReaderPost.h

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#import <CoreData/CoreData.h>
33
#import <WordPressData/BasePost.h>
44

5+
NS_ASSUME_NONNULL_BEGIN
6+
57
typedef NS_ENUM(NSUInteger, SourceAttributionStyle) {
68
SourceAttributionStyleNone,
79
SourceAttributionStylePost,
@@ -20,19 +22,19 @@ extern NSString * const ReaderPostStoredCommentTextKey;
2022

2123
@interface ReaderPost : BasePost
2224

23-
@property (nonatomic, strong) NSString *authorDisplayName;
24-
@property (nonatomic, strong) NSString *authorEmail;
25-
@property (nonatomic, strong) NSString *authorURL;
26-
@property (nonatomic, strong) NSString *siteIconURL;
27-
@property (nonatomic, strong) NSString *blogName;
28-
@property (nonatomic, strong) NSString *blogDescription;
29-
@property (nonatomic, strong) NSString *blogURL;
30-
@property (nonatomic, strong) NSNumber *commentCount;
25+
@property (nonatomic, strong, nullable) NSString *authorDisplayName;
26+
@property (nonatomic, strong, nullable) NSString *authorEmail;
27+
@property (nonatomic, strong, nullable) NSString *authorURL;
28+
@property (nonatomic, strong, nullable) NSString *siteIconURL;
29+
@property (nonatomic, strong, nullable) NSString *blogName;
30+
@property (nonatomic, strong, nullable) NSString *blogDescription;
31+
@property (nonatomic, strong, nullable) NSString *blogURL;
32+
@property (nonatomic, strong, nullable) NSNumber *commentCount;
3133
@property (nonatomic) BOOL commentsOpen;
32-
@property (nonatomic, strong) NSString *featuredImage;
33-
@property (nonatomic, strong) NSNumber *feedID;
34-
@property (nonatomic, strong) NSNumber *feedItemID;
35-
@property (nonatomic, strong) NSString *globalID;
34+
@property (nonatomic, strong, nullable) NSString *featuredImage;
35+
@property (nonatomic, strong, nullable) NSNumber *feedID;
36+
@property (nonatomic, strong, nullable) NSNumber *feedItemID;
37+
@property (nonatomic, strong, nullable) NSString *globalID;
3638
@property (nonatomic) BOOL isBlogAtomic;
3739
@property (nonatomic) BOOL isBlogPrivate;
3840
@property (nonatomic) BOOL isFollowing;
@@ -42,47 +44,47 @@ extern NSString * const ReaderPostStoredCommentTextKey;
4244
@property (nonatomic) BOOL isSavedForLater;
4345
@property (nonatomic) BOOL isSeen;
4446
@property (nonatomic) BOOL isSeenSupported;
45-
@property (nonatomic, strong) NSNumber *organizationID;
46-
@property (nonatomic, strong) NSNumber *likeCount;
47-
@property (nonatomic, strong) NSNumber *score;
48-
@property (nonatomic, strong) NSNumber *siteID;
47+
@property (nonatomic) NSNumber *organizationID;
48+
@property (nonatomic, strong, nullable) NSNumber *likeCount;
49+
@property (nonatomic, strong, nullable) NSNumber *score;
50+
@property (nonatomic, strong, nullable) NSNumber *siteID;
4951
// Normalizes sorting between offset or sortDate depending on the flavor of post.
5052
// Note that this can store a negative value.
51-
@property (nonatomic, strong) NSNumber *sortRank;
53+
@property (nonatomic) NSNumber *sortRank;
5254
// Normalizes the date to sort by depending on the flavor of post.
53-
@property (nonatomic, strong) NSDate *sortDate;
54-
@property (nonatomic, strong) NSString *summary;
55-
@property (nonatomic, strong) NSSet *comments;
56-
@property (nonatomic, strong) NSString *tags;
57-
@property (nonatomic, strong) ReaderAbstractTopic *topic;
58-
@property (nonatomic, strong) NSSet<ReaderCard *> *card;
55+
@property (nonatomic, strong, nullable) NSDate *sortDate;
56+
@property (nonatomic, strong, nullable) NSString *summary;
57+
@property (nonatomic, strong, nullable) NSSet *comments;
58+
@property (nonatomic, strong, nullable) NSString *tags;
59+
@property (nonatomic, strong, nullable) ReaderAbstractTopic *topic;
60+
@property (nonatomic, strong, nullable) NSSet<ReaderCard *> *card;
5961
@property (nonatomic) BOOL isLikesEnabled;
6062
@property (nonatomic) BOOL isSharingEnabled;
6163
@property (nonatomic) BOOL isSiteBlocked;
62-
@property (nonatomic, strong) SourcePostAttribution *sourceAttribution;
64+
@property (nonatomic, strong, nullable) SourcePostAttribution *sourceAttribution;
6365
@property (nonatomic) BOOL isSubscribedComments;
6466
@property (nonatomic) BOOL canSubscribeComments;
6567
@property (nonatomic) BOOL receivesCommentNotifications;
6668

67-
@property (nonatomic, strong) NSString *primaryTag;
68-
@property (nonatomic, strong) NSString *primaryTagSlug;
69+
@property (nonatomic, strong, nullable) NSString *primaryTag;
70+
@property (nonatomic, strong, nullable) NSString *primaryTagSlug;
6971
@property (nonatomic) BOOL isExternal;
7072
@property (nonatomic) BOOL isJetpack;
71-
@property (nonatomic) NSNumber *wordCount;
72-
@property (nonatomic) NSNumber *readingTime;
73-
@property (nonatomic, strong) ReaderCrossPostMeta *crossPostMeta;
74-
@property (nonatomic, strong) NSString *railcar;
73+
@property (nonatomic, strong, nullable) NSNumber *wordCount;
74+
@property (nonatomic, strong, nullable) NSNumber *readingTime;
75+
@property (nonatomic, strong, nullable) ReaderCrossPostMeta *crossPostMeta;
76+
@property (nonatomic, strong, nullable) NSString *railcar;
7577

7678
// Used for tracking when a post is rendered (displayed), and bumping the train tracks rendered event.
7779
@property (nonatomic) BOOL rendered;
7880

7981
// When true indicates a post should not be deleted/cleaned-up as its currently being used.
8082
@property (nonatomic) BOOL inUse;
8183

82-
+ (instancetype)createOrReplaceFromRemotePost:(RemoteReaderPost *)remotePost forTopic:(ReaderAbstractTopic *)topic context:(NSManagedObjectContext *) managedObjectContext;
84+
+ (instancetype)createOrReplaceFromRemotePost:(RemoteReaderPost *)remotePost forTopic:(nullable ReaderAbstractTopic *)topic context:(NSManagedObjectContext *) managedObjectContext;
8385

8486
- (BOOL)contentIncludesFeaturedImage;
85-
- (NSDictionary *)railcarDictionary;
87+
- (nullable NSDictionary *)railcarDictionary;
8688

8789
@end
8890

@@ -95,3 +97,4 @@ extern NSString * const ReaderPostStoredCommentTextKey;
9597

9698
@end
9799

100+
NS_ASSUME_NONNULL_END

Sources/WordPressData/Swift/ReaderCard+CoreDataClass.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ public class ReaderCard: NSManagedObject {
5050

5151
switch remoteCard.type {
5252
case .post:
53-
let post = ReaderPost.createOrReplace(fromRemotePost: remoteCard.post, for: nil, context: context)
53+
let post: ReaderPost
54+
if let remotePost = remoteCard.post {
55+
post = ReaderPost.createOrReplace(fromRemotePost: remotePost, for: nil, context: context)
56+
} else {
57+
return nil
58+
}
5459

5560
// Check if a card already exists with this post to prevent duplicates
5661
if let existingCard = findExistingCard(with: post, context: context) {

Sources/WordPressData/Swift/ReaderPost+PostContentProvider.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ extension ReaderPost {
77
}
88

99
public var isP2Type: Bool {
10-
guard let id = organizationID?.intValue, let type = SiteOrganizationType(rawValue: id) else { return false }
10+
let id = organizationID.intValue
11+
guard let type = SiteOrganizationType(rawValue: id) else { return false }
1112
return type == .p2 || type == .automattic
1213
}
1314

Tests/KeystoneTests/Tests/Services/CommentService+RepliesTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,11 @@ final class CommentService_RepliesTests: CoreDataTestCase {
269269
}
270270

271271
// All comments are visible
272-
XCTAssertEqual(post.comments.count, 24)
273-
XCTAssertEqual(post.comments.filter({ ($0 as! Comment).visibleOnReader }).count, 24)
272+
XCTAssertEqual(post.comments?.count, 24)
273+
XCTAssertEqual(post.comments?.filter({ ($0 as! Comment).visibleOnReader }).count, 24)
274274

275275
// Mark a comment as spam
276-
let spamComment = try XCTUnwrap(post.comments.first { ($0 as! Comment).commentID == 428668 }) as! Comment
276+
let spamComment = try XCTUnwrap(post.comments?.first { ($0 as! Comment).commentID == 428668 }) as! Comment
277277
spamComment.status = CommentStatusType.spam.description
278278
contextManager.saveContextAndWait(mainContext)
279279

@@ -282,8 +282,8 @@ final class CommentService_RepliesTests: CoreDataTestCase {
282282
}
283283

284284
// The spam comment and its two replies are no longer visible
285-
XCTAssertEqual(post.comments.count, 24)
286-
XCTAssertEqual(post.comments.filter({ ($0 as! Comment).visibleOnReader }).count, 21)
285+
XCTAssertEqual(post.comments?.count, 24)
286+
XCTAssertEqual(post.comments?.filter({ ($0 as! Comment).visibleOnReader }).count, 21)
287287
}
288288
}
289289

WordPress/Classes/Services/NotificationSyncMediator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ private extension NotificationSyncMediator {
539539
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [commentIDPredicate, siteIDPredicate])
540540
if let post = try context.fetch(fetchRequest).first {
541541
post.isLiked = isLike
542-
post.likeCount = NSNumber(value: post.likeCount.intValue + (post.isLiked ? 1 : -1))
542+
post.likeCount = NSNumber(value: max((post.likeCount?.intValue ?? 0) + (post.isLiked ? 1 : -1), 0))
543543
}
544544
}
545545
catch {

WordPress/Classes/Services/ReaderPostStreamService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class ReaderPostStreamService {
3939
posts.enumerated().forEach { index, remotePost in
4040
let post = ReaderPost.createOrReplace(fromRemotePost: remotePost, for: readerTopic, context: context)
4141
// To keep the API order
42-
post?.sortRank = NSNumber(value: Date().timeIntervalSinceReferenceDate - Double(((self.pageNumber * Constants.paginationMultiplier) + index)))
42+
post.sortRank = NSNumber(value: Date().timeIntervalSinceReferenceDate - Double(((self.pageNumber * Constants.paginationMultiplier) + index)))
4343
}
4444

4545
// Clean up

WordPress/Classes/ViewRelated/Comments/Controllers/Create/CommentCreateViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ final class CommentCreateViewModel {
3434
wpAssert(siteID != 0, "missing required parameter siteID")
3535
self._save = save
3636

37-
self.suggestionsViewModel = SuggestionsListViewModel.make(siteID: post.siteID)
37+
self.suggestionsViewModel = SuggestionsListViewModel.make(siteID: self.siteID)
3838
self.suggestionsViewModel?.enableProminentSuggestions(postAuthorID: post.authorID)
3939
}
4040

WordPress/Classes/ViewRelated/Likes/LikesListController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ class LikesListController: NSObject {
129129
///
130130
init?(tableView: UITableView, post: ReaderPost, delegate: LikesListControllerDelegate? = nil) {
131131

132-
guard let postID = post.postID else {
132+
guard let postID = post.postID, let siteID = post.siteID else {
133133
return nil
134134
}
135135

136136
content = .post(id: postID)
137137
readerPost = post
138-
siteID = post.siteID
138+
self.siteID = siteID
139139
self.tableView = tableView
140140
self.delegate = delegate
141141

WordPress/Classes/ViewRelated/Reader/Cards/ReaderCrossPostCell.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,13 @@ private final class ReaderCrossPostView: UIView {
138138
}
139139

140140
private func makeHeaderString(for post: ReaderPost) -> NSAttributedString? {
141-
guard let meta = post.crossPostMeta else {
141+
guard let meta = post.crossPostMeta, let blogURL = post.blogURL else {
142142
return nil
143143
}
144144
let template = meta.commentURL.isEmpty ? Strings.siteTemplate : Strings.commentTemplate
145145

146146
let authorName: NSString = (post.authorForDisplay() ?? "") as NSString
147-
let siteName = subdomainNameFromPath(post.blogURL)
147+
let siteName = subdomainNameFromPath(blogURL)
148148
let originName = subdomainNameFromPath(meta.siteURL)
149149

150150
let subtitle = NSString(format: template as NSString, authorName, originName, siteName) as String

WordPress/Classes/ViewRelated/Reader/Comments/ReaderCommentsViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ final class ReaderCommentsViewController: UIViewController, WPContentSyncHelperD
329329
return wpAssertionFailure("post missing")
330330
}
331331
var linkURL = url
332-
if let components = URLComponents(string: url.absoluteString), components.host == nil {
333-
linkURL = components.url(relativeTo: URL(string: post.blogURL)) ?? linkURL
332+
if let components = URLComponents(string: url.absoluteString), components.host == nil, let blogURL = post.blogURL {
333+
linkURL = components.url(relativeTo: URL(string: blogURL)) ?? linkURL
334334
}
335335
let configuration = WebViewControllerConfiguration(url: linkURL)
336336
configuration.authenticateWithDefaultAccount()

0 commit comments

Comments
 (0)