How do I remove all map annotations in swift 2 - xcode

I had working code to remove all map annotations with a button, but after my update to xcode 7 I am running into the error:
Type 'MKAnnotation' does not conform to protocol 'SequenceType'
if let annotations = (self.mapView.annotations as? MKAnnotation){
for _annotation in annotations {
if let annotation = _annotation as? MKAnnotation {
self.mapView.removeAnnotation(annotation)
}
}
}

In Swift 2 annotations is declared as non optional array [MKAnnotation] so you can easily write
let allAnnotations = self.mapView.annotations
self.mapView.removeAnnotations(allAnnotations)
without any type casting.

self.mapView.removeAnnotations(self.mapView.annotations)
If you don't want remove user location.
self.mapView.annotations.forEach {
if !($0 is MKUserLocation) {
self.mapView.removeAnnotation($0)
}
}
Note: Objective-C now have generics, it is no longer necessary cast the elements of 'annotations' array.

SWIFT 5
If you don't want to remove user location mark:
let annotations = mapView.annotations.filter({ !($0 is MKUserLocation) })
mapView.removeAnnotations(annotations)

The issue is that there are two methods. One is removeAnnotation which takes an MKAnnotation object, and the other is removeAnnotations which takes an array of MKAnnotations, note the "s" at the end of one and not the other. Attempting to cast from [MKAnnotation], an array to MKAnnotation a single object or visa versa will crash the program. The line of code self.mapView.annotations creates an array. Thus, if you are using the method removeAnnotation, you need to index the array for a single object within the array, as seen below:
let previousAnnotations = self.mapView.annotations
if !previousAnnotations.isEmpty{
self.mapView.removeAnnotation(previousAnnotations[0])
}
Thus, you can remove various annotations while keeping the users location. You should always test your array before attempting to remove objects from it, else there is the possibly getting an out of bounds or nil error.
Note: using the method removeAnnotations (with an s)removes all annotations.
If you are getting a nil, that implies that you have an empty array. You can verify that by adding an else statement after the if, like so;
else{print("empty array")}

Related

Problems checking to see if a value exists in Swift 2

I'm writing a quiz app and there is a table view to add a subject (The name is saved to core data) and when you select an index path it passes the subject to a detail view controller (this works just fine on its own) but what I'm having trouble with is checking to see if any cards exists (the subject entity has an NSOrderedSet of "Cards"). I keep getting a crash on my two attempts, I've done this in swift before with relationships and tableViews and it's always been fine so I'm not sure what the problem is here. Thank you for the help like always!
My first attempt, although it says "catch block is unreachable because no errors are thrown in do block", it crashes with "Bad Instruction" on the line after "do"
do {
if let firstCard = self.subject?.cards![0] as? Card {
self.currentCard = firstCard
}
} catch {
}
My second attempt, it crashes on the first line
if let firstCard = self.subject?.cards![0] as? Card {
self.currentCard = firstCard
}
My third attempt
if self.subject!.cards != nil {
self.currentCard = self.subject!.cards![0] as! Card
}
My fourth attempt, unwrapping both the subject property and subject, it not rings out self.subject.cards but still crashes
if let firstCard = self.subject!.cards?[0] as? Card {
self.currentCard = firstCard
}
Where the properties are declared
var draggableView = DraggableView!()
var subject : Subject?
var currentCard : Card?
var cardArray = [Card]()
The update with subject method (works perfectly, but put it here just for reference), the subject is passed from another class and this method called at the top of view did load.
func updateWithSubject(subject: Subject) {
if let subject = self.subject {
self.subject = subject
}
}
In all four of your attempts, you do a "forced" unwrapping (!) at some point, which is to be generally avoided. Also, you attempt to explicitly accessing index 0 in your NSOrderedSet; if the set is empty, accessing [0] will yield a runtime exception.
Instead, you could use the .array representation of the NSOrderedSet and use the .first (optional) property of array for a safe access test:
if let firstCard = self.subject?.cards?.array.first ...
I think there's some awkwardness going on in your updateWithSubject method. You're checking if there's a subject already initialized before assigning to it. If that's in your viewDidLoad and only there, the assignment will never happen. The forced unwrapping that follow will surely fail after.

Iterating over a collection in Swift: var vs. let

I have a method that iterates over an array and call other method with every element as argument. If I declare this method as:
func didFinishedListFiles(files: [FileModel]) {
for var fileData in files {
self.downloadSingleFile(NSUUID(UUIDString: fileData.uuid!)!);
}
}
Xcode shows a warning:
Variable 'fileData' was never mutated; consider changing to 'let' constant
But if I change var to let:
func didFinishedListFiles(files: [FileModel]) {
for let fileData in files {
self.downloadSingleFile(NSUUID(UUIDString: fileData.uuid!)!);
}
}
Xcode shows an error:
'let' pattern cannot appear nested in an already immutable context
How is a correct way to implement it without any warnings/errors?
The for-in pattern implicitly uses a constant binding (in the scope it creates. That is, your fileData binding is automatically a local let, and therefore constant for each pass through the loop.
So the following:
for fileData in files { /*...*/ }
...is equivalent to :
var index = 0
while index < files.count {
let fileData = files[index]
//...
index += 1
}
You'd want to add var to the for-in binding only when you want to mutate that binding -- that is, if it's an object reference that you want to be able to point at something else during a single pass through the loop, or a value type that you want to be able to change. But it doesn't look like you're doing either of those things, so using var for this binding would be superfluous here.
(Swift 3 got rid of a lot of the places where you could make implicitly immutable bindings mutable, but left for var as an exception — it's still possible if you want to change something during a loop.)

Returning an Unwrapped Optional in Swift?

When I was sifting through some of the class discussions for AVFoundation, I stumbled upon the following:
class func defaultDeviceWithMediaType(mediaType: String!) -> AVCaptureDevice!
Because optionals are a new concept to me, I'm a bit confused.
The discussion says that this method could either return "the default device with the given media type, or nil if no device with that media type exists." However, if there is a possibility that it's returning nil, why do they unwrap this optional in the return statement? Shouldn't it be AVCaptureDevice?
Then, when looking at an example that utilizes the above method, I find the following:
public lazy var device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
public func hasFlash() -> Bool {
if let d = self.device {
return d.hasFlash
}
return false
}
From what I understand, you would use an if let statement when you have an optional, but because the class defaultDeviceWithMediaType returns an unwrapped variable, why is having an if let necessary?
Thank you so much in advance.
Implicitly unwrapped optional is basically an optional, that gets an ! everywhere you use it. Thats it.
e.g.:
//this:
var number: Int? = ...
print(number!)
//is the same as this:
var number: Int! = ...
print(number)
An implicitly unwrapped optional is only to save you the need of unwrapping it every time you use it, wether with if let or with an !, but it has the same optionality of being nil as a normal optional.
A popular use of Implicitly unwrapped optionals is with outlets - they can't be non-optionals because we don't init them in the init of the VC, but we definitely have them later, so having them unwrapped saves us the need to do annoying things like if let table = self.tableView....
An implicitly unwrapped optional is still an optional - it could be nil. If you simply write self.device.hasFlash, when self.device is nil, you will get an exception.

Swift double unwrapping of Optionals

I understand what optional are in Swift but I just encountered a ”Double Wrapped Optional’, where if I don’t use two '!' Xcode gives an complier error
Value of optional type 'String?' not unwrapped; did you mean to use '!' or ‘?'?
I have the following code, where app is of type NSRunningApplication.
let name: String = app.localizedName!
Why should I have to use two !? Isn’t one enough to unwrap the variable because it is of type var localizedName: String?.
Context:
Xcode want me to use let name: String = app.localizedName!!, otherwise it gives the compiler error above.
The app variable is defined as follow:
var apps = NSWorkspace().runningApplications.filter{$0.activationPolicy == NSApplicationActivationPolicy.Regular}
for app in apps{
//code posted above
…
}
So I know that app is not an optional and will always have a value, nor is it an optional application.
P.S. Is there a way to define type when using fast enumeration? Like for Foo(app) in apps where apps = [AnyObject].
The problem is that NSWorkspace().runningApplications returns an
array of AnyObject which has to be cast to an array of
NSRunningApplication:
let apps = NSWorkspace().runningApplications as! [NSRunningApplication]
let filteredApps = apps.filter {
$0.activationPolicy == NSApplicationActivationPolicy.Regular
}
for app in apps {
let name: String = app.localizedName!
}
Here's why: app is of type AnyObject (id in Objective-C), and doing any lookup on AnyObject introduces a layer of optionality because of the possibility that the method doesn’t exist on the object. localizedName is itself Optional, so you end up with two levels of optional: the outer level is nil if the object doesn’t respond to localizedName, and the inner is nil if 'localizedName' is nil.

Cocoa JSON - Check whether array or dictionary

I am using the Cocoa JSON framework ( http://code.google.com/p/json-framework/ ) to communicate with an API.
The problem is that the API returns a dictionary if there is an error but returns an array of the results if it works.
Is there a good way to detect if the JSONValue is an array or a dictionary?
Thanks.
You can use isKindOfClass: to test whether the object is an instance of NSDictionary or of any subclass thereof.
In most circumstances, you would be better served by a respondsToSelector: check, but this is one case where you really are better off testing its class membership.
Of course, you can test whether it's an array instead of whether it's a dictionary; as long as the API you're using only returns an array or dictionary, the effect is the same.
For true robustness, test both array and dictionary membership, and throw an exception or present an error if the object is neither.
Maybe try to check length property.
if (jsonObj.length) {
//doSomeWork
}
Try this:
if ([YourData isKindOfClass:[NSArray class]])
{
NSLog(#"Array format found");
}
else
{
NSLog(#"Dictionary format found");
}

Resources