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")
}
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 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)")
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 5 years ago.
Improve this question
Is there a way I can fetch contacts using the Contacts framework without an attribute?
Example:
myContactArray = unifiedContactsNotCalled("John")
PS: I know that line is nothing like the real code, it's just a serving suggestion for illustrative purposes 😉
Before I outline how to find those that don't match a name, let's recap how one finds those that do. In short, you'd use a predicate:
let predicate = CNContact.predicateForContacts(matchingName: searchString)
let matches = try store.unifiedContacts(matching: predicate, keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) // use whatever keys you want
(Obviously, you'd wrap that in a do-try-catch construct, or whatever error handling pattern you want.)
Unfortunately, you cannot use your own custom predicates with the Contacts framework, but rather can only use the CNContact predefined predicates. Thus, if you want to find contacts whose name does not contain "John", you have to manually enumerateContacts(with:) and build your results from that:
let formatter = CNContactFormatter()
formatter.style = .fullName
let request = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) // include whatever other keys you may need
// find those contacts that do not contain the search string
var matches = [CNContact]()
try store.enumerateContacts(with: request) { contact, stop in
if !(formatter.string(from: contact)?.localizedCaseInsensitiveContains(searchString) ?? false) {
matches.append(contact)
}
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I get the this string "85:ABC ,83:CFD" after downloading from a web service.I need to store these values to CoreData table TABLE_JOBTITLE. I have the below code
var designationDictionaryArray = results.componentsSeparatedByString(",")
var index: Int = 1
for item in designationDictionaryArray
{
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("TABLE_JOBTITLE",
inManagedObjectContext:managedContext)
let job = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
job.setValue(String(index), forKey: "column_Id")
job.setValue(String(item.componentsSeparatedByString(":")[0]), forKey: "column_Server_Id")
job.setValue(String(item.componentsSeparatedByString(":")[1]), forKey: "column_Job_Name")
print("Column_Id")
print(index)
print("Column_Server_Id")
print(String(item.componentsSeparatedByString(":")[0]))
print("column_Job_Name")
print(String(item.componentsSeparatedByString(":")[1]))
do {
try managedContext.save()
print("saved job title")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
self.desiginationArray.append(item.componentsSeparatedByString(":")[1])
index = index + 1
}
I am able to iterate through each data but the when i store it in the table..It get stored like below
coulmn_Id column_ServerId column_Job_Title
1 83 CFD
1 83 CFD
Could anyone help me with corrected code or reason for this bizarre behavior please..
I suspect one of two things:
The value in result is not as you expect.
The manner in which you are checking the output is faulty.
I lean towards the latter as I do not see any way both entities could be assigned the same column ID in a single run through.
Put breakpoints up top to check the value of results and the array returned from results.componentsSeparatedByString(",").
Show the code you used to iterate through the table to check it. My bet is that you are not showing the true output. What is the output from the print lines within the loop? If it looks something like this:
Column_Id
1
Column_Server_Id
85
column_Job_Name
ABC
Column_ID
2
Column_Server_ID
83
Column_ID
CFD
Then I'd say, for sure, you are not properly reading back your results from Core Data. Let us see where you are getting that final table.
I don't know what the problem was the same code worked as it should.
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 7 years ago.
Improve this question
I have the following object:
(rates)
{
EUR: "1"
RON: 4.5
USD: 1.3
.
.
.
n: INT/STRING
}
Is there any function that does this?
if you care about the index, you can use a 'traditional' for loop - although #Eric points out this will soon be completely removed
for var i = 0; i < rates.count; i++
{
let rate = rates[i]
// do stuff with rate
}
The enumerate approach looks like this
for (index, rate) in rates.enumerate()
{
print("Do stuff with \(rate) at position \(index)")
}
if you just need each object in turn it's a bit easier
for rate in rates
{
// do stuff with rate
}
Because it's a dictionary, no enumerate() required:
var aDictionary: [String: Float] = ["EUR": 1, "RON": 4.5,
"USD": 1.3]
for (index,item) in aDictionary{
print(index,item)
}