How to generate random number without repeating in Swift - ios

I'm extremely new to Swift and programming in general so please be patient with me while I'm trying to get the hang of this.
I've been following a beginners course in Swift from Treehouse and managed to develop a simple app that generates random quotes. So far so good. Now before moving on to more advanced lessons I figured I'd try to update the existing app just to make sure I get some solid practice before moving on.
So here's my question: I've managed to generate a random number through the GameKit framework, but the problem is that sometimes quotes appear consecutively. How can I avoid this from happening?
Here's my code:
import GameKit
struct FactProvider {
let facts = [
"Ants stretch when they wake up in the morning.",
"Ostriches can run faster than horses.",
"Olympic gold medals are actually made mostly of silver.",
"You are born with 300 bones; by the time you are an adult you will have 206.",
"It takes about 8 minutes for light from the Sun to reach Earth.",
"Some bamboo plants can grow almost a meter in just one day.",
"The state of Florida is bigger than England.",
"Some penguins can leap 2-3 meters out of the water.",
"On average, it takes 66 days to form a new habit.",
"Mammoths still walked the Earth when the Great Pyramid was being built."
]
func randomFact() -> String {
let randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: facts.count)
return facts[randomNumber]
}
}

You can store last random number or last fact in a variable and check it in your randomFact function. Like this:
var lastRandomNumber = -1
func randomFact() -> String {
let randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: facts.count)
if randomNumber == lastRandomNumber {
return randomFact()
} else {
lastRandomNumber = randomNumber
return facts[randomNumber]
}
}

Related

Swift compare dates iOS 15 [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 13 days ago.
Improve this question
Can anyone tell me why this doesn’t work right with dates from the server?
I'm trying to compare dates to Now so I can see what was in the past, today and future.
func getDetails(for game: Game) -> String {
let now = Date.now
let gameDate = game.gameDate
if gameDate.compare(now) == .orderedAscending {
print(“past”)
return "past"
}
if gameDate.compare(now) == .orderedDescending {
print(“future”)
return "future"
}
if gameDate.compare(now) == .orderedSame {
print(“today”)
return "today"
}
return "none"
}
My decoder is set decoder.dateDecodingStrategy = .iso8601
All of the dates come back “past” and this is iOS 15+
Thanks for your help in advance.
There is no reason to use the compare() function for dates. Dates conform to the Comparable and Equatable protocols, which means you can use >, <, = >=, and <= to compare them directly.
That said, we don't know what your game.date value is.
I can tell you that Date objects capture the date and time with sub-millisecond precision. Any date you pass into your function is likely to be a few nanoseconds before this code runs, and so be in the past.
consider this code:
let now = Date()
var total = 1
total *= 2
let later = Date()
let equalString = (now == later) ? "equal" : "not equal"
print("The dates are \(equalString)")
if now != later {
print("Dates differ by \(later.timeIntervalSinceReferenceDate - now.timeIntervalSinceReferenceDate)")
}
That code prints "The dates are not equal" because it takes enough time to multiply 1 * 2 that the later date is a tiny fraction of a second later than now.
(On my machine it says that the later date is greater than the now date by 8.499622344970703e-05, or about 8.4 microseconds.)
Take out the math code between the two statements and sometimes you'll get it to say the dates are equal, and other times it will say they are not equal.

CoreData rewards by sum of an attribute rather than individual records

I am working on an app that rewards users when they record a walk, bike ride or bus ride. They are rewarded after a distance reached per journey but I would like to reward them for the total (sum) distance they have recorded with the app using CoreData.
I have tried to look at other Stack Overflow questions on the same topic but have been unsuccessful so far
for journey in journeys where journey.distance > reward.distance {
if earned == nil {
earned = journey
}
It is a bit confusing what you are asking for. To check if sum of some elements is greater than some value it might be best to use reduce in swift. Something like the following:
private func checkRewardAchieved(_ reward: Reward, withJourneys journeys: [Journey]) -> Bool {
return journeys.reduce(0.0, { $0 + $1.distance }) >= reward.distance
}
Here journeys.reduce(0.0, { $0 + $1.distance }) will return a sum of all distances in your array. The sum is then compared to rewards >= reward.distance and result is either true or false.
It might be nice to compute the sum directly with core data though. To do so this answer looks promising.

Measure strong/weak ARC references impact - Impact on execution time [closed]

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 was wondering if (and how much) strong/weak references management have an impact on code execution, especially when freeing objects to which many classes might have a weak reference. At first I mistaken this for ARC, but it's not.
There's a similar question on the same topic, however they don't investigate performance impact or try to pull a number out of it.
Let me be clear: I'm not, in any way, suggesting that ARC or strong/weak might have a bad impact on performance, or say "don't use this". I LOVE this. I'm just curious about how efficient it is, and how to size it.
I've put together this piece of code to get an idea of the performance impact of strong/weak references in execution time.
import Foundation
class Experiment1Class {
weak var aClass: Experiment1Class?
}
class Experiment2Class {
var aClass: Experiment2Class?
}
var persistentClass: Experiment1Class? = Experiment1Class()
var nonWeakPersistentClass: Experiment2Class? = Experiment2Class()
var classHolder = [Experiment1Class]()
var nonWeakClassholder = [Experiment2Class]()
for _ in 1...1000 {
let aNewClass = Experiment1Class()
aNewClass.aClass = persistentClass
classHolder.append(aNewClass)
let someNewClass = Experiment2Class()
someNewClass.aClass = nonWeakPersistentClass
nonWeakClassholder.append(someNewClass)
}
let date = Date()
persistentClass = nil
let date2 = Date()
let someDate = Date()
nonWeakPersistentClass = nil
let someDate2 = Date()
let timeExperiment1 = date2.timeIntervalSince(date)
let timeExperiment2 = someDate2.timeIntervalSince(someDate)
print("Time: \(timeExperiment1)")
print("Time: \(timeExperiment2)")
This piece of code only measure the amount of time it takes to free an object and to set to nil all its references.
IF you execute it in Playground (Xcode 8.3.1) you will see a ratio of 10:1 but Playground execution is much slower than real execution, so I also suggest to execute the above code with "Release" build configuration.
If you execute in Release I suggest you set the iteration count to "1000000" at least, the way I did it:
insert the above code into file test.swift
from terminal, run swiftc test.swift
execute ./test
Being this kind of test, I believe the absolute results makes no to little sense, and I believe this has no impact on 99% of the usual apps...
My results so far shows, on Release configuration executed on my Mac:
Time: 3.99351119995117e-06
Time: 0.0
However the same execution, in Release, on my iPhone 7Plus:
Time: 1.4960765838623e-05
Time: 1.01327896118164e-06
Clearly this test shows there should be little to no concern for real impact on typical apps.
Here are my questions:
Can you think of any other way to measure strong/weak references impact on execution time? (I wonder what strategies the system put in place to improve on this)
What other metrics could be important? (like multi threading optimisation or thread locking)
How can I improve this?
EDIT 1
I found this LinkedList test to be very interesting for a few reasons, consider the following code:
//: Playground - noun: a place where people can play
import Foundation
var n = 0
class LinkedList: CustomStringConvertible {
var count = n
weak var previous: LinkedList?
var next: LinkedList?
deinit {
// print("Muorte \(count)")
}
init() {
// print("Crea \(count)")
n += 1
}
var description: String {
get {
return "Node \(count)"
}
}
func recurseDesc() -> String {
return(description + " > " + (next?.recurseDesc() ?? "FIN"))
}
}
func test() {
var controlArray = [LinkedList]()
var measureArray = [LinkedList]()
var currentNode: LinkedList? = LinkedList()
controlArray.append(currentNode!)
measureArray.append(currentNode!)
var startingNode = currentNode
for _ in 1...31000 {
let newNode = LinkedList()
currentNode?.next = newNode
newNode.previous = currentNode!
currentNode = newNode
controlArray.append(newNode)
measureArray.append(newNode)
}
controlArray.removeAll()
measureArray.removeAll()
print("test!")
let date = Date()
currentNode = nil
let date2 = Date()
let someDate = Date()
startingNode = nil
let someDate2 = Date()
let timeExperiment1 = date2.timeIntervalSince(date)
let timeExperiment2 = someDate2.timeIntervalSince(someDate)
print("Time: \(timeExperiment1)")
print("Time: \(timeExperiment2)")
}
test()
I found the following (running in Release configuration):
I couldn't be able to run more than ~32000 iterations on my phone, it's crashing of EXC_BAD_ACCESS during deinit (yes, during DEINIT... isn't this weird)
Timing for ~32000 iteration is 0 vs 0.06 seconds, which is huge!
I think this test is very CPU intensive because nodes are freed one after the other (if you see the code, only the next one is strong, the previous is weak)... so once the first one is freed, the others fall one after the other, but not altogether.
There is really no such thing as automatic memory management. Memory is managed by retain and release regardless of whether you use ARC. The difference is who writes the code, you or the compiler. There is manual memory management code that you write, and there is manual memory management code that ARC writes. In theory, ARC inserts into your code exactly the same retain and release commands that you would have inserted if you had done this correctly. Therefore the difference in performance should be epsilon-tiny.

how to use calculated values from past steps to determine next step

I'm working on a Survey app based on ResearcKit, where I need to determine the next step based on the sum of the results of the last five steps. This is my very first time programming in swift, and it has been a while since I've done OOP, and I keep making rookie mistakes. Anyway:
In each those five steps, the user chooses one of three sentences that fits her situation the best. Each of these choices results in an answervalue (0, 1 or 2)
If the sum of the answervalues <= 5 the next step is a completionstep (no significant reason for worry), if the sum > 5 they will get a completionstep with tips on what steps to take for help.
A simplified piece of code (with only two steps to sum up) shows where my problem is - it seems like I'm doing something stupid there. Google helped me a lot with all the other predicates for my Survey, mostly with the NSCompundPredicate, but rewriting this to a situation where I could use that seems like the (very) long way around a seemingly simple problem.
Any help is greatly appreciated.
...
let choices = [
ORKTextChoice(text: “never”, value: "0" as NSCoding & NSCopying & NSObjectProtocol),
ORKTextChoice(text: “sometimes”, value: "1" as NSCoding & NSCopying & NSObjectProtocol),
ORKTextChoice(text: “all the time”, value: "2" as NSCoding & NSCopying & NSObjectProtocol)]
 
let question1AnswerFormat : ORKTextChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormat(with: .singleChoice, textChoices: choices)
let question1 = ORKQuestionStep(identifier: "question1", title: “question1”, answer: question1AnswerFormat)
question1.isOptional = false
question1.text = “Do you ever visit StackOverflow?”
steps += [question1]
    
let question2AnswerFormat : ORKTextChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormat(with: .singleChoice, textChoices: choices)
let question2 = ORKQuestionStep(identifier: "question2", title: “question2”, answer: question2AnswerFormat)
question2.isOptional = false
question2.text = “Do you ever post questions on StackOverflow?”
steps += [question2]
//This part is rubbish, it doesn’t even compile, but I hope this shows what I’m looking for
let sum :Int = Int(ORKResultSelector(resultIdentifier: question1.identifier) as! String)! + Int(ORKResultSelector(resultIdentifier: question2.identifier) as! String)!
// ===
let predicate = NSPredicate(value: (sum>2))
let rule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: [(resultPredicate: predicate, destinationStepIdentifier: risk.identifier)], defaultStepIdentifierOrNil: norisk.identifier)
task.setNavigationRule(rule, forTriggerStepIdentifier: question2.identifier)
...

Im getting an error using timed walk test in research kit

Im using timed walk from researchkit test in an app that uses carekit as well. However, I have no idea why I am getting this error. Any help would be greatly appreciated. This is what I have so far. (error states Use of unresolved identifier)
import ResearchKit
public var timedWalk: ORKOrderedTask
{return ORKOrderedTask.timedWalk(withIdentifier: "Timed Walk",intendedUseDescription: "Assessment measures balance", distanceInMeters: 3, timeLimit: 13, includeAssistiveDeviceForm: true, options: .excludeConclusion)
//Create a question.
let title = "Estimate your fall Risk"
let text = "This assessment measure how fast you walk to estimate your fall risk. Start from a sitting position stand walk 10 feet turn around and walk back to sitting position"
***let questionStep = ORKQuestionStep(identifier: "Timed Get up and Go", title: title, text: text, answer: answerFormat)***
questionStep.isOptional = false
//Create an ordered task with a single question
return ORKOrderedTask(identifier: "Timed Walk", steps: [questionStep])
Here's a syntactically correct version of the above code:
public var timedWalk: ORKOrderedTask {
return ORKOrderedTask.timedWalk(withIdentifier: "Timed Walk",
intendedUseDescription:" Assessment measure, the, balance",
distanceInMeters: 3, timeLimit: 13, options: .excludeConclusion)
}

Resources