Reputation: 179
I have a class that gets all the country codes and is supposed to sort them alphabetically. The class runs fine in Xcode for ios but when I copy it to test it in playground I get an error. See picture.
So I stripped back all the code to find the NSMutableArray wasn't declared properly so it changed them to this.
var countries:NSMutableArray = NSMutableArray()
var countryKeys:NSMutableArray = NSMutableArray()
var countryNames:NSMutableArray = NSMutableArray()
It took away the error but the code wont run. No errors and no output.
Anyone know why this code won't run in playground? Is it a bug?
Full code here
struct countryCodes{
var countries:NSMutableArray = NSMutableArray()
var countryKeys:NSMutableArray = NSMutableArray()
var countryNames:NSMutableArray = NSMutableArray()
init(){
for code in NSLocale.ISOCountryCodes() {
let id = NSLocale.localeIdentifierFromComponents([NSLocaleCountryCode: code])
let name = NSLocale(localeIdentifier: "en_UK").displayNameForKey(NSLocaleIdentifier, value: id) ?? "Country not found for code: \(code)"
self.countries.addObject(["key":id,"value":name])
}
self.sortByValue()
}
private func sortByValue(){
let descriptor: NSSortDescriptor = NSSortDescriptor(key: "value", ascending: true)
extractToArrays(self.countries.sortedArrayUsingDescriptors([descriptor]))
}
private func extractToArrays(sortedCountries:NSArray){
for item in self.countries{
self.countryKeys.addObject(item["key"] as! String)
self.countryNames.addObject(item["value"] as! String)
}
}
}
I tried opening a new playground and Immediately I get an error
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
The error
file:///Volumes/External/Xcode%20Projects/MyPlayground3.playground/: error: Playground execution aborted: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x8).
Upvotes: 1
Views: 247
Reputation: 66242
A few comments.
First, value names should begin with capital letters:
struct CountryCodes {
Steer clear of untyped collections like NSArray
and NSDictionary
. Just use the native Swift collection types. So countries
will be an array of [String : String]
:
var countries = [[String : String]]()
In initialization, we need to create the array, and sort it.
init() {
for code in NSLocale.ISOCountryCodes() {
let id = NSLocale.localeIdentifierFromComponents([NSLocaleCountryCode : code])
Swift Optionals represent whether or not data is there. So in the case that data is not there, it's a bad practice to insert a string saying so in your data model. Instead, use guard
to handle that case:
guard let name = NSLocale(localeIdentifier: "en_UK").displayNameForKey(NSLocaleIdentifier, value: id) else {
debugPrint("Country not found for code: \(code)")
break;
}
Once you get the keys and values, append them to the array of countries:
countries += [["key":id, "value":name]]
}
Now that you have all of them, sort by value:
countries = countries.sort() { $0["value"] < $1["value"] }
}
Calculating keys and country names can quickly be done using map
- no need to store them in separate arrays:
var keys : [String] {
return countries.map { $0["key"]! }
}
var names : [String] {
return countries.map { $0["value"]! }
}
}
Here's the full code if you want to try it in a playground:
struct CountryCodes {
var countries = [[String : String]]()
init() {
for code in NSLocale.ISOCountryCodes() {
let id = NSLocale.localeIdentifierFromComponents([NSLocaleCountryCode : code])
guard let name = NSLocale(localeIdentifier: "en_UK").displayNameForKey(NSLocaleIdentifier, value: id) else {
debugPrint("Country not found for code: \(code)")
break;
}
countries += [["key":id, "value":name]]
}
countries = countries.sort() { $0["value"] < $1["value"] }
}
var keys : [String] {
return countries.map { $0["key"]! }
}
var names : [String] {
return countries.map { $0["value"]! }
}
}
let codes = CountryCodes()
codes.countries
codes.keys
codes.names
Notice that this code uses no forced casting (as!
) which causes crashes due to logical errors. The only force operator (!
) being used is in the keys
and names
getters.
Upvotes: 1