Reputation: 16735
I'm presently taking an iOS development course. As an assignment, I'm tasked with enabling iCloud on a project. I've found Tim Roadley's post to be helpful in explaining the process. The wrinkle: I've built my project in Swift.
In particular, one of the "checks" Mr. Roadley built in to check if there's an instance of the iCloud doesn't translate well to Swift. I'm trying to test if there's an instance of an NSURL called iCloud that's instantiated; if so, do one thing, if not do another.
From Mr. Roadley's tutorial:
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloud) {
NSLog(@"iCloud is working");
// a bunch of code
} else {
NSLog(@"iCloud is working");
// a bunch of code
}
So I tried to convert that statement to Swift, as follows:
let iCloud: NSURL = fileManager.URLForUbiquityContainerIdentifier(nil)!
// TODO: having trouble "swiftifying" this line
if (iCloud) {
println("iCloud is working!")
} else {
println("iCloud is NOT working!")
}
The compiler says this: Type 'NSURL' does not conform to protocol 'BooleanType'
What obvious thing am I missing?
Edit:
Thank you all for such fantastic, fast responses. They are greatly appreciated and I've learned something here.
Upvotes: 0
Views: 1220
Reputation: 12768
You can check if it's equal to nil, or you can use the if let
to unwrap it if it exists. fileManager.URLForUbiquityContainerIdentifier(nil)
returns an optional NSURL, so you handle that as such:
Swift 3+
if let cloudURL = fileManager.url(forUbiquityContainerIdentifier: nil) {
print("iCloud is working!")
} else {
print("iCloud is NOT working!")
}
Older Versions
let iCloud = fileManager.URLForUbiquityContainerIdentifier(nil) // Remove the "!", and this should return an optional
if iCloud != nil {
println("iCloud is working!")
} else {
println("iCloud is NOT working!")
}
or with if let
:
if let iCloud = fileManager.URLForUbiquityContainerIdentifier(nil) {
// exists
} else {
// doesn't exist
}
Upvotes: 2
Reputation: 299623
In most cases the best tool for this is if-let
:
if let iCloud = fileManager.URLForUbiquityContainerIdentifier(nil) {
println("iCloud is working!") // And you can access iCloud here
} else {
println("iCloud is NOT working!") // And you don't need iCloud here
}
Of course, if these are very long, you should likely move them into their own functions, and have the "can access" function take a full NSURL
rather than an optional one. That way you don't have lots of code nested inside of an if
. But beyond that, if-let
is the normal tool for this kind of problem.
Upvotes: 1
Reputation: 52632
This line of code will crash your application if fileManager.URLForUbiquityContainerIdentifier doesn't succeed.
let iCloud: NSURL = fileManager.URLForUbiquityContainerIdentifier(nil)!
In Objective-C, this method returns either a URL or nil. In Swift, there are no nil objects. Therefore the method returns an optional URL. By using the ! you force that optional URL to be unwrapped. Unlike Objective-C, you don't get a valid URL or nil, you get a valid URL or a crash.
The variable iCloud is therefore an NSURL*, and it is guaranteed to be not nil (because you would have crashed). There is no point checking whether iCloud is nil or not, because it can't be nil.
If you remove the ! then iCloud becomes an optional NSURL*. In that case, you can check whether it has a value by checking
if (iCloud != nil)
The syntax
if (iCloud)
is illegal. An if statement requires a boolean value, and Swift doesn't just convert everything to a boolean value (it was legal at some point, but then people figured out that optional booleans were a nightmare if this was allowed).
Upvotes: 1