Created
January 27, 2022 14:46
-
-
Save nivbp7/8ff337d3879a43f3edfe6ef1ee506b40 to your computer and use it in GitHub Desktop.
Contentful Controller for testing completion handler is invoked twice on failure case
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Contentful | |
final class ContentfulController: NSObject { | |
// -------------------------------------------------------------------------------- | |
// MARK: | |
// MARK: Singleton | |
static let shared = ContentfulController() | |
// -------------------------------------------------------------------------------- | |
// MARK: | |
// MARK: Constants - Private | |
private let spaceID = <SpaceID> | |
private let deliveryAPIAccessToken = <Token> | |
// -------------------------------------------------------------------------------- | |
// MARK: | |
// MARK: Interface - Private | |
private var client: Client! | |
// -------------------------------------------------------------------------------- | |
// MARK: | |
// MARK: Initialization/deinitalization | |
private override init() { | |
super.init() | |
let contentTypeClasses: [EntryDecodable.Type] = [ | |
ContentfulPost.self, | |
ContentfulAuthor.self, | |
] | |
client = Client(spaceId: spaceID, | |
accessToken: deliveryAPIAccessToken, | |
contentTypeClasses: contentTypeClasses) | |
} | |
// -------------------------------------------------------------------------------- | |
// MARK: | |
// MARK: Interface - Public | |
func fetchPosts(completion: @escaping (Result<[ContentfulPost],Error>) -> Void) { | |
client.fetchArray(of: ContentfulPost.self) { (result) in | |
switch result { | |
case .success(let response): | |
print(response.items.count) | |
completion(.success(response.items)) | |
case .failure(let error): | |
print("error in fetchPosts") | |
completion(.failure(error)) | |
} | |
} | |
} | |
} | |
final class ContentfulPost: EntryDecodable, FieldKeysQueryable, Codable { | |
static let contentTypeId: String = "post" | |
let id: String | |
let localeCode: String? | |
let updatedAt: Date? | |
let createdAt: Date? | |
let title: String? | |
let type: String? | |
var author: ContentfulAuthor? | |
let readingTime: Int? | |
let body: Int? //This is intentionally set as in Int in order to have a fail case | |
var heroImage: Asset? | |
var video: Asset? | |
public required init(from decoder: Decoder) throws { | |
let sys = try decoder.sys() | |
id = sys.id | |
localeCode = sys.locale | |
updatedAt = sys.updatedAt | |
createdAt = sys.createdAt | |
let fields = try decoder.contentfulFieldsContainer(keyedBy: ContentfulPost.FieldKeys.self) | |
self.title = try fields.decodeIfPresent(String.self, forKey: .title) | |
self.body = try fields.decodeIfPresent(Int.self, forKey: .body) | |
self.type = try fields.decodeIfPresent(String.self, forKey: .type) | |
self.readingTime = try fields.decodeIfPresent(Int.self, forKey: .readingTime) | |
try fields.resolveLink(forKey: .heroImage, decoder: decoder) { [weak self] heroImage in | |
self?.heroImage = heroImage as? Asset | |
} | |
try fields.resolveLink(forKey: .author, decoder: decoder, callback: {[weak self] (author) in | |
self?.author = author as? ContentfulAuthor | |
}) | |
try fields.resolveLink(forKey: .video, decoder: decoder, callback: {[weak self] (video) in | |
self?.video = video as? Asset | |
}) | |
} | |
enum FieldKeys: String, CodingKey { | |
case title, type, author, readingTime, body, heroImage, video | |
} | |
} | |
final class ContentfulAuthor: EntryDecodable, FieldKeysQueryable, Codable { | |
static let contentTypeId: String = "author" | |
let id: String | |
let localeCode: String? | |
let updatedAt: Date? | |
let createdAt: Date? | |
let name: String? | |
let url: String? | |
var image: Asset? | |
public required init(from decoder: Decoder) throws { | |
let sys = try decoder.sys() | |
id = sys.id | |
localeCode = sys.locale | |
updatedAt = sys.updatedAt | |
createdAt = sys.createdAt | |
let fields = try decoder.contentfulFieldsContainer(keyedBy: ContentfulAuthor.FieldKeys.self) | |
self.name = try fields.decodeIfPresent(String.self, forKey: .name) | |
self.url = try fields.decodeIfPresent(String.self, forKey: .url) | |
try fields.resolveLink(forKey: .image, decoder: decoder) { [weak self] image in | |
self?.image = image as? Asset | |
} | |
} | |
enum FieldKeys: String, CodingKey { | |
case name, url, image | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment