iOS Calendar App Time Zone List - ios

As you can see in the screen below, iOS Calendar app shows the list of available time zone in City, Country format.
I want to attain the same list. Where can I get this list?

You cannot get a "City, County" format, but you can get a "City, Continent" format using this piece of code:
let timeZones = TimeZone.knownTimeZoneIdentifiers.flatMap{ id->String? in
let components = id.components(separatedBy: "/")
guard components.count == 2, let continent = components.first, let city = components.last else {return nil}
return "\(city), \(continent)"
}
Output will be:
"Abidjan, Africa", "Accra, Africa", "Addis_Ababa, Africa", "Algiers, Africa", "Asmara, Africa", "Bamako, Africa", "Bangui, Africa", "Banjul, Africa"...

TimeZone has a static function knownTimeZoneIdentifiers which returns an array of String identifiers. Documentation

Related

iOS TimeZone get three letter abbreviation

I need to get three/four letter abbreviation for the country called 'Africa/Nairobi', I have tried using
print(TimeZone(abbreviation: "SAST")?.identifier) from the NSTimeZone.abbreviationDictionary, results nil.
How to get the three/four letter abbreviations for this country 'Africa/Nairobi'. Thanks in Advance
You can get a full standard localized name of timezone by the following method.
let timezone:TimeZone = TimeZone.init(identifier: "Africa/Nairobi") ?? TimeZone.current
print(timezone.localizedName(for: .generic, locale: .autoupdatingCurrent))
print(timezone.localizedName(for: .standard, locale: .autoupdatingCurrent))
Will give you following output
Optional("East Africa Time")
Optional("East Africa Time")
I think now you get easily get EAT form East Africa Time by spliting and combining string
let fullName = timezone.localizedName(for: .standard, locale: .autoupdatingCurrent) ?? ""
var result = ""
fullName.enumerateSubstrings(in: fullName.startIndex..<fullName.endIndex, options: .byWords) { (substring, _, _, _) in
if let substring = substring { result += substring.prefix(1) }
}
print(result)
Will give you out put
EAT

Can Locale identify country by currency code?

I was looking for that answer in here, and also on official documentation, but I can't find the answer for that. I've got currency codes (e.g. "EUR"). I need to get country code (e.g "EU"). So I've seen that I can do it inversely (getting currency code by using country code), but I was trying to change this solution for my needs, and I got nil as result. Also I know I can use simple solution - remove last letter from currency code to get country code (It works for most cases from my API data, but not everywhere) - but I feel this approach is not safe. So my question is like in title: Can I identify country from currency code by using Locale?
Here is my approach:
with NSLocale
extension NSLocale {
static func currencySymbolFromCode(code: String) -> String? {
let localeIdentifier = NSLocale.localeIdentifier(fromComponents: [NSLocale.Key.currencyCode.rawValue : code])
let locale = NSLocale(localeIdentifier: localeIdentifier)
return locale.object(forKey: NSLocale.Key.countryCode) as? String
}
}
with Locale
extension Locale {
static let countryCode: [String: String] = Locale.isoCurrencyCodes.reduce(into: [:]) {
let locale = Locale(identifier: Locale.identifier(fromComponents: [NSLocale.Key.currencyCode.rawValue: $1]))
$0[$1] = (locale.regionCode)
}
}
A currency can be associated with multiple countries, you should create your own custom data implementation, such as following json
{
"EUR":"PL",
"USD":"CA"
}
Create a file in your Xcode project and name it for e.g. data.json, and paste such JSON as above, finally use following method
func getCountryCode(currency: String) -> String? {
var countryCode: String?
let url = Bundle.main.url(forResource: "data", withExtension: "json")!
do {
let data = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: String]
countryCode = json?[currency]
} catch {
print(error.localizedDescription)
}
return countryCode
}
Usage
if let countryCode = getCountryCode(currency: "EUR") {
print(countryCode)
}
The answer from #AamirR is a bit not accurate.
EUR != PL, PL = PLN = Poland
USD != CA, CA = CAD = Canada
In majority of cases (with some exceptions), first 2 letters of currency code = ISO 3166-2 country code:
PLN = PL = Poland
GBP = GB = Great Britain
USD = US = United States of America
AMD = AM = Armenia
CZK = CZ = Czech Republic
BRL = BR = Brazilia
and so on ...
So if you have currency codes you can get country names (with 99% accuracy) as follows:
let currencyCode = "USD"
let countryCode = String(currencyCode.prefix(2))
let countryName = Locale.current.localizedString(forRegionCode: countryCode)
print(countryName)
Optional("United States")
However, as some commented above, EU for example, is not a country, and looks like in your specific case you do not need a country flag, you need "currency flag", so for EUR you will display EU flag, which is correct, as you cant determine which EU country flag to display - France, Germany, etc ... so this approach might work for mapping currencies to countries flags.
Though there are some exceptions, in terms of first 2 letters of currency code not matching first 2 letters of country name, from ISO 3166-2 country code perspective, they still match:
CHF = CH = Switzerland
HRK = HR = Croatia
DKK = DK = Denmark
... and so on
The other interesting pattern is that first 2 letters of currency codes, would usually match country internet domain, but again, there are some exceptions from this too.

How to get a set of EKCalendars properly

I now develop an iOS App that shows a list of iCloud EKCalendars.
My swift codes can get a set of iCloud EKCalendars, but the order is always different.
Could anyone give me advice to get the set in order?
let eventStore = EKEventStore()
let sources = eventStore.sources
for source in sources {
if (source.title == "iCloud") {
let calendars = source.calendars(for: .event)
for calendar in calendars {
print("calendar title = " + calendar.title)
}
}
}
Example of the result of the codes:
calendar title = title1
calendar title = title6
calendar title = title5
calendar title = title3
calendar title = title4
calendar title = title2
So let calendars = source.calendars(for: .event) is of type Set<EKCalendar>, by definition a Set is data type that is not ordered so whenever you iterate through a set it could always be in different order, the only thing that Set enforces is that there is only one instance of the object it the set.
If you want to have calendars ordered you will have to order it by yourself, one is to order them by title or calendarIdentifier.
Just sort the Set, the result is an ordered array:
let eventStore = EKEventStore()
let sources = eventStore.sources.filter{ $0.title == "iCloud" }
for source in sources {
let calendars = source.calendars(for: .event).sorted{ $0.title < $1.title }
calendars.forEach { print("calendar title = ", $0.title) }
}

Dealing with memory usage due to high element count in Firebase query

I'm writing code that is appending elements from firebase to an array to perform a simple search using a textfield.
The code for the method is below:
var filteredEvents = [Event]()
var eventsArray = [Event]()
fileprivate func fetchEvents(){
print("Fetching events....")
//create a reference to the location in the database that you want to pull from and observe the value there
let ref = Database.database().reference().child("events")
// this will retur a snapshot with all the data at that location in the database and cast the results as a dictionary for later use
ref.observe(.value, with: { (snapshot) in
guard let dictionaries = snapshot.value as? [String: Any] else{
return
}
//does the job of sorting dictionary elements by key and value
//displaying the key and each corresponding value
dictionaries.forEach({ (key,value) in
// print(key, value)
//creating an eventDictionary to store the results of previous call
guard let eventDictionary = value as? [String: Any] else{
return
}
//will cast each of the values as an Event based off my included struct
//Make sure to create a model it is the only way to have the data in the format you want for easy access
let events = Event(currentEventKey: key, dictionary:eventDictionary)
// appends that to the dictionary to create the dictionary of events
self.eventsArray.append(events)
})
// will sort the array elements based off the name
self.eventsArray.sort(by: { (event1, event2) -> Bool in
return event1.currentEventName.compare(event2.currentEventName) == .orderedAscending
})
// will again reload the data
self.collectionView?.reloadData()
}) { (err) in
print("Failed to fetch events for search")
}
}
I personally did not think of the chance where I may have a great number of events. I won't be able to just append all 1000+ events to a dictionary. That will ratchet my memory up. Is there anyway I could have the query respond to the text field. Also could anyone maybe help me with the line for the query that would perform this action but not destroy my memory?
"events" : {
"CCDS" : {
"attend:count" : 1,
"event:date" : {
"end:date" : "08/09/2017",
"end:time" : "7:00 PM",
"start:date" : "08/09/2017",
"start:time" : "5:00 PM"
},
"event:description" : "Happy hour is more joyful in the summer thanks to Center City District Sips, which offers discounted drinks and appetizers every Wednesday evening. Catch up with old friends and make a few new ones as Center City’s best bars and restaurants host the summer’s happiest hour every Wednesday from 5-7 p.m. Enjoy $5 cocktails, $4 wine, $3 beers and half-price appetizers at dozens and dozens of bars and restaurants.",
"event:imageURL" :someURL",
"event:location" : {
"event:city" : "Philadelphia",
"event:state" : "PA",
"event:street:address" : "660 Chestnut St",
"event:zip" : 19106
},
"event:name" : "Center City District Sips"
},
"MIA" : {
"attend:count" : 1,
"event:date" : {
"end:date" : "09/03/2017",
"end:time" : "7:00 PM",
"start:date" : "09/02/2017",
"start:time" : "12:00 PM"
},
"event:description" : "Budweiser Made in America Festival is an annual music festival held in Philadelphia and formerly simultaneously held in Los Angeles.Sponsored by Anheuser–Busch and produced by Live Nation, the event features several stages that continuously host live music from a wide range of genres including hip hop, rock, pop, R&B, and EDM.",
"event:imageURL" : "someURL",
"event:location" : {
"event:city" : "Philadelphia",
"event:state" : "PA",
"event:street:address" : "Ben Franklin Parkway",
"event:zip" : 19130
},
"event:name" : "Made In America"
}
},
For example I want to pull all information about an event that I have searched for using the query. So if I begin to type in Made in America it will pull all relevant information from the events tab about that event
This is what I currently have
fileprivate func fetchEvents(searchString: String){
print("Fetching events....")
//create a reference to the location in the database that you want to pull from and observe the value there
let ref = Database.database().reference().child("events")
// this will retur a snapshot with all the data at that location in the database and cast the results as a dictionary for later use
let query = ref.queryOrdered(byChild: "event:name").queryEqual(toValue: searchString)
print(query)
query.observeSingleEvent(of: .value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String: Any] else{
print(snapshot.value)
return
}
print(snapshot.value)
}) { (err) in
print("Failed to fetch event data", err)
}
}
Returns this
(/events { ep = Made In America; i = "event:name"; sp = Made In America; })
It appears the question is
"How can I query for a value contained in a child node?"
Given a structure similar to the original
"events" : {
"CCDS" : {
"attend:count" : 1,
"event:imageURL" :"someURL",
"event:name" : "Center City District Sips"
"MIA" : {
"attend:count" : 1,
"event:imageURL" : "someURL",
"event:name" : "Made In America"
a Firebase query would return the node you want.
If the user typed in Made In America and tapped the search button here's the query to return that node in a snapshot.
let searchString = "Made In America"
let ref = self.ref.child("events")
let query = ref.queryOrdered(byChild: "event:name").queryEqualTo(searchString)
query.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let eventDict = snap.value as! [String: Any]
let attendCount = eventDict["attend:count"] as! String
let url = eventDict["event:imageURL"} as! String
}
})
If you want to do a partial string match, where the user could type in just a few characters like Made the code is similar but you need to let firebase return all of the matches starting with Made...
The query would look like this
let startString = "Made"
let endString = "Made" + "\\uf8ff"
let query = ref.queryOrdered(byChild: "event:name")
.queryStarting(atValue: startString)
.queryEnding(atValue: endString")
The "\uf8ff" is a character at a very high code level in Unicode - because of that it encompasses all of the preceeding characters.
However, querying 'on the fly' can create an unresponsive or sluggish UI so it's not recommended.
An alternative is to create a seperate node that contains a lot less info and contains the elements the user would search for and a reference to the event node.
So the main node containing all the data looks like this
"events" : {
"-uyuh8s8j8jsdas" : {
"event": "CCDS"
"attend:count" : 1,
"event:imageURL" : "someURL",
"-y88jsijsijjids" : {
"event": "MIA"
"attend:count" : 1,
"event:imageURL" : "someURL",
and a 'smaller' node would look like this
events_for_searching
-uyuh8s8j8jsdas
event:name: "Center City District Sips"
-y88jsijsijjids
event:name: "Made In America"
With this, you could load all of the nodes from the events_for_searching into an array (then filter the array as the user types) which would make the UI very responsive and when the user selects a name, you can then use the key from that node as a reference to load the data from the events node via an observeSingleEvent function.
EDIT
In response to a comment, I wanted to add a bit more detail in code.
Here's my structure
"events" : {
"event_0" : {
"event:name" : "An Event"
},
"event_1" : {
"event:name" : "Made In America"
}
},
and the code to query for event:name: Made In America
let searchString = "Made In America"
let ref = self.ref.child("events")
let query = ref.queryOrdered(byChild: "event:name").queryEqual(toValue: searchString)
query.observeSingleEvent(of: .value, with: { (snapshot) in
guard let dictionary = snapshot.value as? [String: Any] else{
print(snapshot.value)
return
}
print(snapshot.value)
}) { (err) in
print("Failed to fetch event data", err)
}
and the output
Optional({
"event_1" = {
"event:name" = "Made In America";
};
})

NSLocale to Country name [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have seen this answered in objective-C, but I don't know how to convert to swift.
My app receives the public information of a user from Facebook, and I need to convert the locale into the country name.
FBRequestConnection.startForMeWithCompletionHandler({
connection, result, error in
user["locale"] = result["locale"]
user["email"] = result["email"]
user.save()
println(result.locale)
})
For example, for a French user, the code sends "Optional(fr_FR)" to the log. However I need it to just send the country name. According to localeplanet.com, the display name of "fr_FR" is "French (France)". So in the log all I want is "France".
Working off of this SO question, I've whipped up a Swift translation. Try this:
let locale: NSLocale = NSLocale(localeIdentifier: result.locale!)
let countryCode = locale.objectForKey(NSLocaleCountryCode) as String
var country: String? = locale.displayNameForKey(NSLocaleCountryCode, value: countryCode)
// According to the docs, "Not all locale property keys
// have values with display name values" (thus why the
// "country" variable's an optional). But if this one
// does have a display name value, you can print it like so.
if let foundCounty = country {
print(foundCounty)
}
Updated for Swift 4:
FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"locale"]).start { (connection, result, error) in
guard let resultDictionary = result as? [String:Any],
let localeIdentifier = resultDictionary["locale"] as? String else {
return
}
let locale: NSLocale = NSLocale(localeIdentifier: localeIdentifier)
if let countryCode = locale.object(forKey: NSLocale.Key.countryCode) as? String,
let country = locale.displayName(forKey: NSLocale.Key.countryCode, value: countryCode) {
print(country)
}
}

Resources