Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
308 views
in Technique[技术] by (71.8m points)

ios - Or parameterized API call crashing in Swift

I am making a call to an API where I want have status equal to final or in progress. Here is the call I am using:

let request = NSMutableURLRequest(url: NSURL(string: "https://sportspage-feeds.p.rapidapi.com/games?status=in%20progress||status=final")! as URL,
                                                cachePolicy: .useProtocolCachePolicy,
                                            timeoutInterval: 10.0)

It works perfectly in Postman, but when trying it in my app it is crashing with this error:

Fatal error: Unexpectedly found nil while unwrapping an Optional value: file

Is there a different way to use or in Swift?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have manually percent encoded the space, but you have not percent encoded the two pipe characters. As a result the initialiser for NSURL fails, returning nil. Since you have force-unwrapped this value, your app then crashes.

You can use the function .addingPercentEncoding(withAllowedCharacters:) to percent encode a string appropriately and then create a URL.

Both percent encoding a string and creating a URL can fail, so these operations return an optional. You should use conditional unwrapping rather than force unwrapping to avoid crashes if these operations fail.

Many NS classes have bridged Swift equivalents including URLRequest for NSURLRequest and URL for NSURL. Idiomatic Swift eschews the use of an NS class when a Swift equivalent exists.

Use something like

if let urlStr = "https://sportspage-feeds.p.rapidapi.com/games?status=in progress||status=final".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(urlStr) {
    let request = URLRequest(url, timeoutInterval: 10)
    ...
}   

As Matt pointed out in a comment, the correct way to construct a URL in iOS is to use URLComponents. This allows you to specify each component of the URL independently and not worry about things like manual percent encoding.

The use of URLComponents is particularly important where you collect input from the user and they could attempt to manipulate the resulting URL string.

var components = URLComponents()
components.scheme = "https"
components.host = "sportspage-feeds.p.rapidapi.com"
components.path = "/games"
components.queryItems = [(URLQueryItem(name:"status", value:"in progress||status=final"))]

if let url = components.url {
    let request = URLRequest(url, timeoutInterval: 10)
    ...
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...