Created
August 5, 2021 20:06
-
-
Save daltonclaybrook/3eba9081b6e03800fd44b8072333c167 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 libspacekit | |
public struct AstroPhoto: Equatable { | |
public let title: String | |
public let url: URL | |
} | |
private struct AstroPhotoContext { | |
let fetcher: AstroPhotoFetcher | |
let completion: AstroPhotoFetcher.PhotoCompletion | |
} | |
/// Utility for fetching the NASA astronomy photo of the day | |
public final class AstroPhotoFetcher { | |
public typealias PhotoCompletion = (Result<AstroPhoto, PhotoError>) -> Void | |
public enum PhotoError: Error { | |
case noPhotoFound | |
case invalidPhotoURLs | |
} | |
private let nasaAPIKey: String | |
public init(nasaAPIKey: String) { | |
self.nasaAPIKey = nasaAPIKey | |
} | |
public func fetchPhoto(with completion: @escaping PhotoCompletion) { | |
let context = AstroPhotoContext(fetcher: self, completion: completion) | |
let contextPointer = UnsafeMutablePointer<AstroPhotoContext>.allocate(capacity: 1) | |
contextPointer.initialize(to: context) | |
nasaAPIKey.withCString { apiKeyPointer in | |
fetch_photo_of_the_day( | |
apiKeyPointer, | |
photoCallback(info:rawContext:), | |
UnsafeMutableRawPointer(contextPointer) | |
) | |
} | |
} | |
// MARK: - Completion handlers | |
fileprivate func handleDidReceivePhoto(_ info: PhotoInfo?, completion: PhotoCompletion) { | |
guard let info = info else { | |
return completion(.failure(.noPhotoFound)) | |
} | |
let title = String(cString: info.title) | |
let urlString = String(cString: info.url) | |
guard let url = URL(string: urlString) else { | |
return completion(.failure(.invalidPhotoURLs)) | |
} | |
let photo = AstroPhoto(title: title, url: url) | |
completion(.success(photo)) | |
} | |
} | |
// MARK: - Callback | |
private func photoCallback(info: UnsafeMutablePointer<PhotoInfo>?, rawContext: UnsafeMutableRawPointer?) { | |
guard let rawContext = rawContext else { return } | |
let contextPointer = rawContext.assumingMemoryBound(to: AstroPhotoContext.self) | |
let context = contextPointer.pointee | |
defer { | |
contextPointer.deinitialize(count: 1) | |
contextPointer.deallocate() | |
} | |
context.fetcher.handleDidReceivePhoto(info?.pointee, completion: context.completion) | |
} |
This file contains hidden or 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 libspacekit | |
public struct AstroPhoto: Equatable { | |
public let title: String | |
public let url: URL | |
} | |
/// Utility for fetching the NASA astronomy photo of the day | |
public final class AstroPhotoFetcher { | |
public typealias PhotoCompletion = (Result<AstroPhoto, PhotoError>) -> Void | |
public enum PhotoError: Error { | |
case noPhotoFound | |
case invalidPhotoURLs | |
} | |
private let nasaAPIKey: String | |
public init(nasaAPIKey: String) { | |
self.nasaAPIKey = nasaAPIKey | |
} | |
public func fetchPhoto(with completion: @escaping PhotoCompletion) { | |
// Todo: implement | |
} | |
// MARK: - Completion handlers | |
fileprivate func handleDidReceivePhoto(_ info: PhotoInfo?, completion: PhotoCompletion) { | |
guard let info = info else { | |
return completion(.failure(.noPhotoFound)) | |
} | |
let title = String(cString: info.title) | |
let urlString = String(cString: info.url) | |
guard let url = URL(string: urlString) else { | |
return completion(.failure(.invalidPhotoURLs)) | |
} | |
let photo = AstroPhoto(title: title, url: url) | |
completion(.success(photo)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment