Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I've already seen other questions asking about how many times the app has been opened. I want to send a local notification when the user uses the app for 31 consecutive days.
Would this be a NSUserDefaults discovery method or would I need to use an analytics API?
Use UserDefault. In appdelegate's didFinishLaunch method check for days count
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let kLastUsed = "LastUsedTime"
let kDaysCount = "DaysCount"
let currentDateTimeInterval = Int(Date().timeIntervalSinceReferenceDate)
var storedDaysCount:Int = UserDefaults.standard.integer(forKey: kDaysCount)
if storedDaysCount >= 31 {
//show pushNotifications
}
else {
let lastDateTimeInterval = UserDefaults.standard.integer(forKey: kLastUsed)
let diff = currentDateTimeInterval - lastDateTimeInterval
if diff > 86400 && diff < 172800 {
//next day. increase day count by one
storedDaysCount = storedDaysCount + 1
UserDefaults.standard.set(storedDaysCount, forKey: kDaysCount)
}
else if diff > 86400 {
//not next day. reset counter to 1
UserDefaults.standard.set(1, forKey: kDaysCount)
}
UserDefaults.standard.set(currentDateTimeInterval, forKey: kLastUsed)
}
return true
}
Just expanding on Hitesh's awesome answer to make it more suitable for realtime testing.
You cannot change the date in the simulator settings like you can on a real device. And if you change the date on your real device you might get some Apple server-Xcode syncing issues and Xcode will ask you to register your device in the Developer Portal again.
*Test on a real device using the current time because the UserDefaults needs the date and store from the real device.
To test for minutes or seconds just change all the Ints to Doubles and change the condition to something finer like if storedDaysCount >= 0.0000000015.
let kLastUsed = "LastUsedTime"
let kDaysCount = "DaysCount"
let currentDateTimeInterval = Double(Date().timeIntervalSinceReferenceDate)
var storedDaysCount:Double = UserDefaults.standard.double(forKey: kDaysCount)
if storedDaysCount >= 0.000000000015 {
print("storedDaysCount = \(storedDaysCount)")
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
Improve this question
Since there's only documentation for Node.js, it's unclear of how to use FirebaseFunctions Swift library. I will appreciate if someone can provide some basic examples.
As #jnpdx pointed out in their comment, Firebase only support writing Callable Cloud Functions in Node.js.
What you can do though is call your Cloud Functions from Swift, as shown in the documentation here:
functions.httpsCallable("addMessage").call(["text": inputField.text]) { result, error in
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain {
let code = FunctionsErrorCode(rawValue: error.code)
let message = error.localizedDescription
let details = error.userInfo[FunctionsErrorDetailsKey]
}
// ...
}
if let data = result?.data as? [String: Any], let text = data["text"] as? String {
self.resultField.text = text
}
}
And to handle errors:
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain {
let code = FunctionsErrorCode(rawValue: error.code)
let message = error.localizedDescription
let details = error.userInfo[FunctionsErrorDetailsKey]
}
// ...
}
So it's usually a two-step process:
Write your Cloud Functions in Node.js.
Call them from any of the client side SDKs mentioned in that documentation link
See also the examples in the Firebase Functions Swift QuickStart (thanks to Paul for sharing that link).
See also the examples in the Firebase Functions Swift QuickStart
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I basically have this issue where this Reporting API only allows me to call it once each 90 seconds.
I'm building an app where I get the data each time you open it, to get the latest data, but I somehow need to stop the app from calling the API if it was before 90s wait and show cached data, how can I do this?
Each time you go to ping the API compare the current time to the last time it was done. Kinda like this:
// set defaults for storage
let userDefaults = UserDefaults.standard
// set time
let date = Date()
//Check Storage
if let theDate = userDefaults.object(forKey: "date") as? Date {
// on successful load compare times
if date.timeIntervalSince(theDate) > 90000 /* I think it runs in milliseconds so I put 90 seconds worth there*/ {
// do API call here
// save time
userDefaults.set(date as! Any, forKey: "date")
} else {
print("too soon")
} else {
// data not successfully loaded
// try to ping API here too
// save time
userDefaults.set(date as! Any, forKey: "date")
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I want to know when a song is played on music app and get its info. But I don't want to get all songs from library, It's just the songs that was played since the app starts to scan.
It's like you play something, then you open the app and it scan what you played.
I've searching about this but didn't find nothing, and I don't know where to start to implement this.
First, add the NSAppleMusicUsageDescription key to your Info.plist with a description of why you need access to the user's media library
Then you can find all songs that have been played since a certain time with the following code:
import MediaPlayer
#IBAction func getSongs(_ sender: Any) {
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Calendar.current.startOfDay(for: Date()))!
// Check for permissions
switch MPMediaLibrary.authorizationStatus() {
case .authorized, .restricted:
fetchSongPlayed(since: yesterday)
case .notDetermined:
MPMediaLibrary.requestAuthorization { _ in
let auth = MPMediaLibrary.authorizationStatus()
if auth == .authorized || auth == .restricted {
self.fetchSongPlayed(since: yesterday)
}
}
case .denied:
print("No access to the Media Library")
}
}
func fetchSongPlayed(since date: Date) {
let query = MPMediaQuery.songs()
var results = [MPMediaItem]()
if let songs = query.items {
results = songs.filter { ($0.lastPlayedDate ?? Date.distantPast) > date }
} else {
print("Can't fetch songs")
}
// Now do whatever you want with results
// It's an array of MPMediaItem
print(results.count)
}
One more tip: sync some music from iTunes to your device as the Simulator doesn't have any bye default. There's a way to add it to the simulator but it's just easier to test on device.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Lets say I have some rules for displaying a message like below
between 00:00-12:00 -> morning
between 12:01-14:00 -> noon
between 14:01-17:00 -> afternoon
between 17:00-23:59 -> evening
if current mobile time is between 00:00 and 12:00 I should get morning
How can I do that please guide.
This should do the job
func check(time: NSDate) -> String? {
let formatter = NSDateFormatter()
formatter.dateFormat = "HH:mm"
formatter.timeZone = NSTimeZone(name: "GMT")
guard let
beginNoon = formatter.dateFromString("12:00"),
beginAfternoon = formatter.dateFromString("14:00"),
beginEvening = formatter.dateFromString("17:00")
else { return nil }
if time.compare(beginNoon) == .OrderedAscending { return "Morning" }
if time.compare(beginAfternoon) == .OrderedAscending { return "Noon"}
if time.compare(beginEvening) == .OrderedAscending { return "Afternoon" }
return "Evening"
}
Test
check(formatter.dateFromString("10:00")!) // "Morning"
check(formatter.dateFromString("13:00")!) // "Noon"
check(formatter.dateFromString("15:00")!) // "Afternoon"
check(formatter.dateFromString("22:00")!) // "Evening"
Considerations
Your ranges are inconsistent
Here you are including the left and right boundaries
00:00-12:00 -> morning
here you are including only the right boundary
12:01-14:00 -> noon
14:01-17:00 -> afternoon
and here only the left boundary :)
between 17:00-23:59
In my code, the left boundary in only included while the right one is excluded.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Hey is that possible to change background image in an app using hour and minutes? For example sunrise at 7:30 and it will change background to a sunrise picture and time goes by it will change into morning at specific Hour and minutes too. If it can how to setup in swift. Thank you
If you're talking about changing the iOS background on the HomeScreen, no. Swift does not give you that much capability over iOS.
However, if you are talking about changing the background in your app to reflect the time of day, then it is absolutely possible. The Best way to go about it would be to check the time as soon as your app is opened using a function in your AppDelegate.swift file called
applicationDidBecomeActive
Once there, you need to capture the date and set it to a global variable (see here for more information regarding how to do this if you're unfamiliar)
after you have set the Date to a global variable, you will need to tell your application to change the background while the app is loading your view. This is just pseudocode of what the code will actually look like, but I hope it helps:
let sunRiseTime : Date = //insert date you would like the background to change here.
let noon : Date = //insert date for noon here
let sunriseBackgroundImage : UIImage = //insert image you would like for the sunrise here
let noonBackgroundImage : UIImage = //insert image you would like for noon here.
if(dateGlobalVariable >= sunriseTime){
self.backgroundImage = sunriseBackgroundImage
}else if(dateGlobalVariable >= noon{
self.backgroundImage = noonBackgroundImage
}
//continue this for as many images as you have.
hope this helps! let me know if you have any questions!
You can do it like that:
func setupTimer(hour: Int, minute: Int, second: Int, newColor: UIColor){
let calendar = Calendar.current.date(bySettingHour: hour, minute: minute, second: second, of: Date())
let timer = Timer(fireAt: calendar!, interval: 0, target: self, selector: #selector(changeBackground(_:)), userInfo: UIColor.gray, repeats: true)
RunLoop.main.add(timer, forMode: .common)
}
#objc func changeBackground(_ timer: Timer?){
if let newColor = timer?.userInfo as? UIColor {
DispatchQueue.main.async {
self.view.backgroundColor = newColor
}
}
}
Below method in AppDelgate will do the job.
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
This will get called when the application is opened/launched. change the app's background according to the time.