@@ -34,10 +34,7 @@ struct ITunesSearchAppStoreSearcher: AppStoreSearcher {
3434 /// - Throws: A `MASError.unknownAppID(appID)` if `appID` is invalid.
3535 /// Some other `Error` if any other problem occurs.
3636 func lookup( appID: AppID , inRegion region: ISORegion ? ) async throws -> SearchResult {
37- guard let url = lookupURL ( forAppID: appID, inRegion: region) else {
38- fatalError ( " Failed to build URL for \( appID) " )
39- }
40- let results = try await loadSearchResults ( url)
37+ let results = try await getSearchResults ( from: try lookupURL ( forAppID: appID, inRegion: region) )
4138 guard let result = results. first else {
4239 throw MASError . unknownAppID ( appID)
4340 }
@@ -62,10 +59,9 @@ struct ITunesSearchAppStoreSearcher: AppStoreSearcher {
6259
6360 var appSet = Set < SearchResult > ( )
6461 for entity in entities {
65- guard let url = searchURL ( for: searchTerm, inRegion: region, ofEntity: entity) else {
66- fatalError ( " Failed to build URL for \( searchTerm) " )
67- }
68- appSet. formUnion ( try await loadSearchResults ( url) )
62+ appSet. formUnion (
63+ try await getSearchResults ( from: try searchURL ( for: searchTerm, inRegion: region, ofEntity: entity) )
64+ )
6965 }
7066
7167 return Array ( appSet)
@@ -77,13 +73,14 @@ struct ITunesSearchAppStoreSearcher: AppStoreSearcher {
7773 /// - appID: App ID.
7874 /// - region: The `ISORegion` of the storefront in which to lookup apps.
7975 /// - entity: OS platform of apps for which to search.
80- /// - Returns: URL for the lookup service or nil if appID can't be encoded.
76+ /// - Returns: URL for the lookup service.
77+ /// - Throws: An `MASError.urlParsing` if `appID` can't be encoded.
8178 private func lookupURL(
8279 forAppID appID: AppID ,
8380 inRegion region: ISORegion ? ,
8481 ofEntity entity: Entity = . desktopSoftware
85- ) -> URL ? {
86- url ( " lookup " , URLQueryItem ( name: " id " , value: String ( appID) ) , inRegion: region, ofEntity: entity)
82+ ) throws -> URL {
83+ try url ( " lookup " , URLQueryItem ( name: " id " , value: String ( appID) ) , inRegion: region, ofEntity: entity)
8784 }
8885
8986 /// Builds the search URL for an app.
@@ -92,23 +89,25 @@ struct ITunesSearchAppStoreSearcher: AppStoreSearcher {
9289 /// - searchTerm: term for which to search in MAS.
9390 /// - region: The `ISORegion` of the storefront in which to lookup apps.
9491 /// - entity: OS platform of apps for which to search.
95- /// - Returns: URL for the search service or nil if searchTerm can't be encoded.
92+ /// - Returns: URL for the search service.
93+ /// - Throws: An `MASError.urlParsing` if `searchTerm` can't be encoded.
9694 private func searchURL(
9795 for searchTerm: String ,
9896 inRegion region: ISORegion ? ,
9997 ofEntity entity: Entity = . desktopSoftware
100- ) -> URL ? {
101- url ( " search " , URLQueryItem ( name: " term " , value: searchTerm) , inRegion: region, ofEntity: entity)
98+ ) throws -> URL {
99+ try url ( " search " , URLQueryItem ( name: " term " , value: searchTerm) , inRegion: region, ofEntity: entity)
102100 }
103101
104102 private func url(
105103 _ action: String ,
106104 _ queryItem: URLQueryItem ,
107105 inRegion region: ISORegion ? ,
108106 ofEntity entity: Entity = . desktopSoftware
109- ) -> URL ? {
110- guard var components = URLComponents ( string: " https://itunes.apple.com/ \( action) " ) else {
111- return nil
107+ ) throws -> URL {
108+ let urlBase = " https://itunes.apple.com/ \( action) "
109+ guard var urlComponents = URLComponents ( string: urlBase) else {
110+ throw MASError . urlParsing ( urlBase)
112111 }
113112
114113 var queryItems = [
@@ -122,12 +121,15 @@ struct ITunesSearchAppStoreSearcher: AppStoreSearcher {
122121
123122 queryItems. append ( queryItem)
124123
125- components . queryItems = queryItems
124+ urlComponents . queryItems = queryItems
126125
127- return components. url
126+ guard let url = urlComponents. url else {
127+ throw MASError . urlParsing ( " \( urlBase) ? \( queryItems. map ( \. description) . joined ( separator: " & " ) ) " )
128+ }
129+ return url
128130 }
129131
130- private func loadSearchResults ( _ url: URL ) async throws -> [ SearchResult ] {
132+ private func getSearchResults ( from url: URL ) async throws -> [ SearchResult ] {
131133 let ( data, _) = try await networkSession. data ( from: url)
132134 do {
133135 return try JSONDecoder ( ) . decode ( SearchResultList . self, from: data) . results
0 commit comments