So I am trying to follow Flurry.com rules about sending Age and Gender before you start the flurry.
switch UserSettings().gender {
case "Male":
Flurry.setGender("m")
case "Female":
Flurry.setGender("f")
default:
break;
}
let ageComponents = Calendar.current.dateComponents([.year],
from: UserSettings().dateofbirth,
to: Date())
let age = Int32(ageComponents.year!)
Flurry.setAge(age);
Flurry.startSession("XXXXXXXXXXX", with: FlurrySessionBuilder
.init()
.withCrashReporting(true)
.withLogLevel(FlurryLogLevelAll))
return true
}
However while I can see it is sending it to Flurry.
2021-05-09 21:44:44.169277+0800 DRN1[1881:365938] -[FlurryStreamCoreBuffer streamMessage:]: msg = <FlurryStreamUserGender: 0x281ea80c0, type = 168, json = { "fl.frame.version" : 1, "fl.demo.gender" : 1 }>
I can't seem to see it in my dash board. I am wondering what I might be doing wrong.
The screenshot is showing the dashboard that only has built in charts for estimated age and gender. The easiest way to check is to go to the "App Activity" dashboard, click on "Breakouts", and selected either Reported Age or Reported Gender.
Related
everyone! I'm a new member of Stack Overflow, just like I'm beginner on swift programming. I'm making this post to find out a solution for the following case:
I'm creating on Swift an app using the Command Line Tool for inputing data. The app basically works as an authenticator. As an example, if someone types USA for the country name and the age is 17, so the program will return a message like "You can not apply to this position". Otherwise, if the country name is USA and the age is equal or higher than 18, so the message returns is "You can forward to the next step". I've tried many times to set this conditions, but it's not working. I'm already knows that the function readLine() is an Optional String, but how can I make my program work correctly? It follows my code above to you understanding my thoughts.
I really appreciate any help. Again, I'm beginner and I'm already studying Swift languages, but I'm seeking some solution that handles Integers and Strings and comparing both data types. Thank you very much!
My code is:
import Foundation
print("Enter your country: ")
var country = readLine()
print("Enter your age: ")
var age = readLine()
if var country, var age = readLine(){
if country == "USA" && age < "18" {
print("You're not allowed to apply to this position.")
} else {
print("You can forward to the next step.")
}
}
PS: As you see, I'm using wrongly the variable age as an String, but I want to convert it to an Int type and then, check if the country name is the same than the value I assigned to or the age is equal or higher than 18. But not found a solution so far.
I'm trying to find a solution that compares two different types on Swift, using Command Line Tool and the readLine() function to check if a condition is true or not. If it's true, an output message will show that the user can proceed to the next step, otherwise he will not be permitted to follow. I'm keeping for an explanation on internet since few days, but not found anything that might help me. I hope to get some help using the Stack Overflow forum to some useful answer.
First one, readline() means you read the current to the end of current line . As your code when you check condition you call readLine() again. The wrong part is here.
I recommend you to read first then do all your logic. You just need to read only one time at first
print("Enter your country: ")
var country = readLine()
print("Enter your age: ")
var ageString = readLine()
Next, check if it is nil or not ( because option value which is value can be nil)
if country == nil || ageString == nil {
print("Error because one of them is nil")
fatalError()
}
Then check if can convert to Int or not. Reach here you sure that the ageString is not nil because you have checked above. So you just simply convert
guard let ageString = ageString else {
print("Error age nil")
fatalError()
}
guard let age = Int(ageString) else {
print("Error age not a number")
fatalError()
}
Then after all, you just check your condition
Full code will be like this
print("Enter your country: ")
var country = readLine()
print("Enter your age: ")
var ageString = readLine()
// check nil first if nil return or do something first and not get to the rest
if country == nil || ageString == nil {
print("Error because one of them is nil")
fatalError()
}
guard let ageString = ageString else {
print("Error age nil")
fatalError()
}
guard let age = Int(ageString) else {
print("Error age not a number")
fatalError()
}
if country == "USA" && age < 18 {
print("You're not allowed to apply to this position.")
} else {
print("You can forward to the next step.")
}
Other methods is use if let to achieve so no force unwrap
print("Enter your country: ")
var country = readLine()
print("Enter your age: ")
var ageString = readLine()
// check nil first if nil return or do something first and not get to the rest
if country == nil || ageString == nil {
print("Error because one of them is nil")
fatalError()
}
if let ageString = ageString {
if let age = Int(ageString) {
if country == "USA" && age < 18 {
print("You're not allowed to apply to this position.")
} else {
print("You can forward to the next step.")
}
} else {
print("Error age not a number")
fatalError()
}
}
SOLUTION SOLVED!
Hey, guys, first of all I want to thank you all for your helpful answers, which helped me a lot. I've got finally a solution, and am going to share it with you.
What did I done? I just created two variables, one String and another Integer. Then, using the if var to force unwrapping of the Int variable, I've made an if statement to check if the both conditions are true (in the case, if the person is from USA and has an age equals or higher than 18). Now, the program is running on the same way I just wanted. If you are from USA but has no 18 years, output returns a message that you can not apply. Otherwise, you're able to forward.
I'll let the code above. If you want to make some comments or any suggestions, it'll be welcome.
Again, thank you very much for all your answers.
var countryCheck = "USA"
var ageCheck: Int = 18
print("Enter your country: ")
var country = readLine()
print("Enter your age: ")
var age = readLine()
if var countryCheck = country, var ageCheck = Int(age!) {
if countryCheck == "USA" && ageCheck >= 18 {
print("You can apply.")
} else {
print("You can not apply to this position.")
}
}
I hope this help you :)
import Foundation
print("Enter your country: ")
if let country = readLine() {
if let num = Int(country) {
print(num)
}
}
let country = readLine()
let age = readLine()
if let USA = country,
let num1 = Int(USA),
let num2 = Int(USA) {
print("The age of \(num1) and \(num2) is \(num1 + num2)")
}
I want get the language code of the device (en, es...) in my app written with Swift. How can get this?
I'm trying this:
var preferredLanguages : NSLocale!
let pre = preferredLanguages.displayNameForKey(NSLocaleIdentifier, value: preferredLanguages)
But this returns nil.
In Swift 3
let langStr = Locale.current.languageCode
It's important to make the difference between the App language and the device locale language (The code below is in Swift 3)
Will return the Device language:
let locale = NSLocale.current.languageCode
Will return the App language:
let pre = Locale.preferredLanguages[0]
Swift 4 & 5:
Locale.current.languageCode
Swift 3 & 4 & 4.2 & 5
Locale.current.languageCode does not compile regularly. Because you did not implemented localization for your project.
You have two possible solutions
1) String(Locale.preferredLanguages[0].prefix(2))
It returns phone lang properly.
If you want to get the type en-En, you can use Locale.preferredLanguages[0]
2)
Select Project(MyApp)->Project (not Target)-> press + button into Localizations, then add language which you want.
In Swift 3:
NSLocale.current.languageCode
TL;DR:
Use Bundle.main.preferredLocalizations[0] to get the language your app's UI is currently displayed in. Don't use Locale.current because it describes the region format (time, currency, distance, etc) and has nothing to do with language.
Detailed Answer:
The definite answer about how to get the language(!) code for the language your app's UI is displayed in comes from Apple engineer Quinn "The Eskimo", and I quote/paraphrase for Swift:
Locale.current returns the current locale, that is, the value set by Settings > General > Language & Region > Region Formats. It has nothing to do with the language that your app is running in. It's perfectly reasonable, and in fact quite common, for users in the field to have their locale and language set to 'conflicting' values. For example, a native English speaker living in France would have the language set to English but might choose to set the locale to French (so they get metric weights and measures, 24 time, and so on).
The language that your app runs in is determined by the language setting, that is, Settings > General > Language & Region > Preferred Language Order. When the system runs your app it takes this list of languages (the preferred list) and matches it against the list of languages that your app is localised into (the app list). The first language in the preferred list that exists in the app list is the language chosen for the app. This is what you'll find in the first entry of the main bundle's preferredLocalizations array.
Language Name from Code
To get the human-readable name of a language from its code, you can use this:
let langCode = Bundle.main.preferredLocalizations[0]
let usLocale = Locale(identifier: "en-US")
var langName = ""
if let languageName = usLocale.localizedString(forLanguageCode: langCode) {
langName = languageName
}
This will give you the English name of the current UI language.
To get current language used in your app (different than preferred languages)
NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)!
swift 3
let preferredLanguage = Locale.preferredLanguages[0] as String
print (preferredLanguage) //en-US
let arr = preferredLanguage.components(separatedBy: "-")
let deviceLanguage = arr.first
print (deviceLanguage) //en
Locale.current.languageCode returns me wrong code, so I use these extensions:
extension Locale {
static var preferredLanguageCode: String {
guard let preferredLanguage = preferredLanguages.first,
let code = Locale(identifier: preferredLanguage).languageCode else {
return "en"
}
return code
}
static var preferredLanguageCodes: [String] {
return Locale.preferredLanguages.compactMap({Locale(identifier: $0).languageCode})
}
}
Swift 5.4:
let languagePrefix = Locale.preferredLanguages[0]
print(languagePrefix)
you may use the below code it works fine with swift 3
var preferredLanguage : String = Bundle.main.preferredLocalizations.first!
I want to track the language chosen by the user in Settings app every time the user launches my app - that is not yet localized (my app is in English only). I adopted this logic:
create an enum to to make it easier to handle the languages in array
enum Language: String {
case none = ""
case en = "English"
case fr = "French"
case it = "Italian"
} // add as many languages you want
create a couple of extension to Locale
extension Locale {
static var enLocale: Locale {
return Locale(identifier: "en-EN")
} // to use in **currentLanguage** to get the localizedString in English
static var currentLanguage: Language? {
guard let code = preferredLanguages.first?.components(separatedBy: "-").last else {
print("could not detect language code")
return nil
}
guard let rawValue = enLocale.localizedString(forLanguageCode: code) else {
print("could not localize language code")
return nil
}
guard let language = Language(rawValue: rawValue) else {
print("could not init language from raw value")
return nil
}
print("language: \(code)-\(rawValue)")
return language
}
}
When you need, you can simply use the extension
if let currentLanguage = Locale.currentLanguage {
print(currentLanguage.rawValue)
// Your code here.
}
In Swift, You can get the locale using.
let locale = Locale.current.identifier
This is what I use in Swift 5 Xcode 11:
Inside the class variables:
let languagePrefix = Bundle.main.preferredLocalizations.first?.prefix(2)
This comes as a string. It returns 2 characters, i.e. "en", "es", "de"...
From this I can easily determine what language to display:
if languagePrefix == "es" { self.flipCard.setTitle("última carta", for: .normal) }
if languagePrefix == "en" { self.flipCard.setTitle("Last Card", for: .normal) }
If you want the full information of the language, then remove ?.prefex(2)
in most cases you want to get the language code of the current app UI, to send over an API to get localized response
extension Bundle {
var currentLocalizedUILanguageCode: String {
guard let code = Bundle.main.preferredLocalizations.first?.components(separatedBy: "-").first else {
return Locale.current.languageCode ?? "en"
}
return code
}
}
use like
headers["X-Language"] = Bundle.main.currentLocalizedUILanguageCode
use this function for get your system's current language code from iOS devices
func getSystemLanguageCode() -> String {
UserDefaults.standard.removeObject(forKey: "AppleLanguages")
let pref_Language = NSLocale.preferredLanguages[0] as String //"fr-IN"
let language = pref_Language.components(separatedBy: "-") //["fr","IN"]
let lang_Code = language.first?.lowercased() ?? "" //"fr"
UserDefaults.standard.set([lang_Code], forKey: "AppleLanguages")
return lang_Code
}
Almost none of the answers are correct. This is working Swift 5.7 solution.
extension Locale {
// Gets the language of the device, had to remove the content of AppleLanguages since `preferredLanguages`
// is combining the result from multiple APIs. AppleLanguage is then being set to the old value
static var preferredLanguageCode: String {
let appleLanguages = UserDefaults.standard.stringArray(forKey: kLanguage)
UserDefaults.standard.removeObject(forKey: kLanguage)
guard let preferredLanguage = preferredLanguages.first,
let code = Locale(identifier: preferredLanguage).languageCode else {
UserDefaults.standard.set(appleLanguages, forKey: kLanguage)
return "en"
}
UserDefaults.standard.set(appleLanguages, forKey: kLanguage)
return code
}
}
What I have: A snapshot of all users with a bunch of if statements that eventually returns an array of users that get displayed.
What I need: The array of end users to be used in a .query in the line preceding the snapshot.
Why do I need this: This line is so that the entire database of users is not run on the client.
More specifically, what do I need to query for: A) Users who have a child "caption"(timestamp) with a timestamp that is in today, AND, B) who are 3000 miles from the current user.
JSON of DB
"people" : {
"02PdiNpmW3MMyJt3qPuRyTpHLaw2" : {
"Coordinates" : {
"latitude" : -25.809620667034363,
"longitude" : 28.321706241781342
},
"PhotoPosts" : "https://firebasestorage.googleapis.com/v0/b/daylike-2f938.appspot.com/o/images%2F02PdiNpmW3MMyJt3qPuRyTpHLaw2%2FPhotoPosts?alt=media&token=24fee778-bcda-44e3-aa26-d7c2f8509740",
"caption" : 1602596281762, /// this is timestamp
"postID" : "02PdiNpmW3MMyJt3qPuRyTpHLaw2"
},
"e1" : “cvvvv666",
"e2" : "aol.com",
" "postID" : "0RnqWV7Gd9Z0bUW9nUvizMQOjK73",
"users" : "cvvvv666#aol.com"
},
.
var dict = CLLocation()
...
dict = CLLocation(latitude: lat, longitude: lon)
...
let thisUsersUid = Auth.auth().currentUser?.uid
//this line below is where the refArtists2 query should go. in other words send all users to device that meet the 2 if statements, which is represented by self.people.append(peopl)//
let refArtists2 = Database.database().reference().child("people").queryOrdered(byChild: "caption").queryEqual(toValue: ANY Timestamp in today).queryOrdered(byChild:Coordinates). queryEqual(toValue:ThoseCoordinates which make the distance to current user less than 3000 miles)
refArtists2.observe(DataEventType.value, with: { snapshot in
if snapshot.childrenCount>0{
self.people.removeAll()
for people in snapshot.children.allObjects as! [DataSnapshot] {
if people.key != thisUsersUid {
let peopleObject = people.value as? [String: AnyObject]
let peopleCoordinates = peopleObject?["Coordinates"] as? String
let peoplecaption = peopleObject?["caption"] as? Int //is timestamp
let peoplepostID = peopleObject?["postID"] as? String
let coordSnap = people.childSnapshot(forPath: "Coordinates")
guard let lat = coordSnap.childSnapshot(forPath: "latitude").value as? CLLocationDegrees else { return }
guard let lon = coordSnap.childSnapshot(forPath: "longitude").value as? CLLocationDegrees else { return }
let locCoord = CLLocation(latitude: lat, longitude: lon)
let coordSnap12 = people.childSnapshot(forPath: "caption").value as? Int ?? 0
let date = Date(timeIntervalSince1970: TimeInterval(coordSnap12)/1000.0)
//let secondsInDay = 86400
**if Calendar.current.isDateInToday(date)** {
let distance = locCoord.distance(from: self.dict)
print(distance, "distancexy")
**if distance/1609.344 < 3000**{
let peopl = Userx(Coordinates: peopleCoordinates, distance:distance, caption: peoplecaption, postID: peoplepostID)
self.people.append(peopl)
let d = people.key as! String
self.printPersonInfo(uid:d) ///////This is used to reload the data
} else {
print ("w")
}
} else {
print ("alphaaa")
}
}
print("aaaaaaaa", self.people.map {$0.distance})
}
self.people.sort { ($0.distance ?? 0) < ($1.distance ?? 0) } ////////This sorting with distance is used with returning the cell. people is used as uid array to return the cell.
}
})
} else {
print("no")
}
})
Ancillary caveat: the self.people.sort { ($0.distance ?? 0) < ($1.distance ?? 0) }sorting is important, so the queries should not impede that. I am a bit concerned with using queryOrdered in that it orders the array of users in the wrong order. If it does, a C) query should be: The order of the users must be with the closest users to the logged in user first. The furthest from the logged in user must go last in the array.
Another way of asking this would be: Instead of running a snapshot of all users, how do you query the snapshot's 'end result sort' when making the snapshot?
The timestamp is seconds since 1970
My attempt at the date query below. I took the code and tried to put the code that gets the date before the actual query(currently the code that gets the date is after the snapshot of all users).
var ppp: String! ////this should be the uid of all users in db
let people = Database.database().reference().child("people").child(self.ppp).child("captions")
people.observe(DataEventType.value, with: { snapshot in
let captionss = snapshot.value as? Int ?? 0
let date = Date(timeIntervalSince1970: TimeInterval(captionss)/1000.0)
let query1 = Database.database().reference().child("people").queryOrdered(byChild: "caption").where?(isDateInToday(date))
Edit: This answer is in Firestore, not Realtime Database. However, the concepts are the same.
The question is several questions in one; asking about distance, compound queries and how to query Firebase in general. I will post this answer to address the second two and distance queries are addressed in the comment to the question.
Once the query pattern is understood, they become easier and most importantly; it becomes more obvious that how your data is structured depends on what queries you want to run against that data.
Suppose we have a users collection with user documents - each documentId is the users uid
users
uid_0
name: "Leroy"
and then we have the posts for the users - each post contains some text, a timestamp of the post, the uid of the user that posted it, what the topic is and a url of a picture that appears in the post. Notice I am storing posts in a separate collection; why read in a bunch of user data when we only want to know about their post.
posts
post_id
postText: "pretty flowers"
postDate: "20201103"
postUrl: "www....."
postUid: "uid_0"
postTopic: "flowers"
Let suppose we want to get posts from today that are about flowers, and then also get the posters name and output who posted the message and what they said.
To do this we will need a compound query and then a subquery to retrieve the posters name as well.
func getTodaysPostsAboutFlowers() {
let postsCollection = self.db.collection("posts")
let query = postsCollection.whereField("postDate", isEqualTo: "20201103").whereField("postTopic", isEqualTo: "flowers")
query.getDocuments(completion: { snapshot, error in
if let err = error {
print(err.localizedDescription)
return
}
guard let docs = snapshot?.documents else { return }
for doc in docs {
let postText = doc.get("postText") as? String ?? "No text"
guard let postersUid = doc.get("postUid") as? String else { return }
self.outputPostTextAndUserName(withText: postText, andUid: postersUid)
}
})
}
The above performs a compound query on both the postDate field as the postTopic field.
The above then calls another function to retrieve the users name and output both the name and what they said
func outputPostTextAndUserName(withText: String, andUid: String) {
let usersCollection = self.db.collection("users")
let theUserDoc = usersCollection.document(andUid)
theUserDoc.getDocument(completion: { documentSnapshot, error in
if let err = error {
print(err.localizedDescription)
return
}
if let doc = documentSnapshot {
let postersName = doc.get("name") as? String ?? "No Name"
print("\(postersName) posted: \(withText)")
}
})
}
and the output
Leroy posted: pretty flowers
As you can see, there's no need to load all of the users, no need to iterate over results etc. Even if you have a billion users, this will only return a subset of that data which is a best practice when working with huge data sets; only get the data you're interested in.
Edit. The OP is asking about querying for nodes containing today. The simple solution is to have one child node containing a timestamp which would contains specific date data and then another child node just containing today data in YYYYMMDD format.
people
uid_x
timetamps: 9023490823498 //Date(timeIntervalSince1970:
todaystamp: "20201106" // yyyymmdd format
that makes querying for nodes that contain today very simple.
I am trying to pull blood glucose values from a query I have made to get the last 10 in the Health App. I am able to pull the data from the Health app and get it in the form for a single entry:
(2017-02-21 13:13:00 -0500 - 2017-02-21 13:13:00 -0500), 80 mg/dL 52D7A973-7853-455C-9308-0E339153A3BE "Health" (10.2.1) metadata: {
HKWasUserEntered = 1;}
I am able to pull the startdate (and endDate) from this by adding:
guard let timing = reading?.endDate as Date? else {
print("timing scheme didn't work.")
return
}
print(timing)
and pull the type (HKQuantityTypeIdentifierBloodGlucose) by writing
guard let bg = reading?.sampleType as HKSampleType? else {
print("bg scheme didn't work")
return
}
print(bg)
However, I can not figure out to print the actual blood glucose value (ie. 80 mg/dL).
I tried:
let bg = reading.quantity
but I got the error
Value of type 'Optional<HKSample>' has no member 'quantity'
If anyone has insight to this, it would be extremely helpful! Thank you in advance!
// To read blood glucose:
let gluco = reading as? HKQuantitySample
if let bg = gluco?.quantity {
print(bg)
}
Does anyone know of a way to get the screen name, or model name/number from a display that is connected to the system? I've been looking around for quite some time to see if there is a way to do this. The only method I've seen anyone post only works with a deprecated API (CGDisplayIOServicePort), (and there's not replacement listed for that API), so that isn't really an option.
Basically, I am wanting to give the user a list of connected screens to display the output of the app, and I feel like giving them a list of names of the displays would be much more elegant and nicer than whatever the ID is that is returned from NSScreen or CGGetActiveDisplayList, etc. It has to possible, when you go to the display preferences in OS X it gives you the names of the displays there. Anyone have any ideas?
macOS 10.15 Catalina introduced a new property localizedName for getting the external display name:
NSScreen.screens.forEach {
print($0.localizedName)
}
You can get the names of connected screens directly from IOReg
func screenNames() -> [String] {
var names = [String]()
var object : io_object_t
var serialPortIterator = io_iterator_t()
let matching = IOServiceMatching("IODisplayConnect")
let kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
matching,
&serialPortIterator)
if KERN_SUCCESS == kernResult && serialPortIterator != 0 {
repeat {
object = IOIteratorNext(serialPortIterator)
let info = IODisplayCreateInfoDictionary(object, UInt32(kIODisplayOnlyPreferredName)).takeRetainedValue() as NSDictionary as! [String:AnyObject]
if let productName = info["DisplayProductName"] as? [String:String],
let firstKey = Array(productName.keys).first {
names.append(productName[firstKey]!)
}
} while object != 0
}
IOObjectRelease(serialPortIterator)
return names
}
let names = screenNames()