Performing functions with valueForKey - swift

I am trying to get my app to perform functions. I have two attributes per item (quantity and price) that I want to multiply together and then total for all the didSelectRow items on the list. There is two sections on my tableView. Section 0 is regular and moved to section 1 with didSelectRow. (I only explain this because it comes into play further down)
My code so far is...
`func cartTotalFunc() {
itemFetchRequest().returnsObjectsAsFaults = false
do {
let results = try moc.executeFetchRequest(itemFetchRequest())
print("===\(results)")
// Calculate the grand total.
var grandTotal = 0
for order in results {
let SLP = order.valueForKey("slprice") as! Int
let SLQ = order.valueForKey("slqty") as! Int
grandTotal += SLP * SLQ
}
print("\(grandTotal)")
cartTotal.text = "$\(grandTotal)" as String
} catch let error as NSError {
print(error)
}
}
`
slprice and slqty are strings in Core Data. I am trying to cast them as Int so they will do the arithmetic. I had this working but it totaled every item instead of only the crossed off ones (section 1). I gave it a rest for a while and now when I come back to try to work on it again Xcode is giving me an error of, "can not Could not cast value of type 'NSTaggedPointerString' (0x104592ae8) to 'NSNumber' (0x1051642a0)."
Can anyone help with this, please?

Related

Why is my lineString not converting to mapShape in geoSwift - (only happens with one specific search), could be external library bug?

Im using the GEOSwift Library: https://github.com/GEOSwift/GEOSwift
My best guess is that if you look at the string image linked, it looks as if its not a proper circle, so maybe it is a bug in the library? But i am not at all sure about this!
Im having an issue only when i enter one specific linestring.
My app takes an array of route coordinates, converts them into WKT String (representing a line). It then Creates a buffer around this line, then converts this into a mapShape.
It runs fine, until i search one specific route.
It fails here:
func bufferPolyline(routeCoords: [CLLocationCoordinate2D], completion: #escaping (_ bufferCoordsArray: [LatLng]) -> ()) {
var wktString = ""
var i = 0
while i < routeCoords.count {
let lat = routeCoords[i].latitude
let lng = routeCoords[i].longitude
if i == routeCoords.count-1 {
let wktLast = " \(lng) \(lat)"
wktString += "\(wktLast)"
i += 1
}
if i >= 1 && i <= routeCoords.count-2 {
let wktMid = " \(lng) \(lat),"
wktString += "\(wktMid)"
i += 1
}
if i == 0 {
let wktFirst = "\(lng) \(lat),"
wktString += "\(wktFirst)"
i += 1
}
}
let linestring = Geometry.create("LINESTRING(\(wktString))")!
let string = linestring.buffer(width: 0.05)!
guard let shapeLine = string.mapShape() as? MKPolygon else {
preconditionFailure() // FAILURE HAPPENS HERE.
}
}
Here are links to images to see how it looks:
LineString - https://imgur.com/a/7OLPZkM
String - https://imgur.com/a/KJRfpRX
the linestring, and string values are still coming through even when shapeLine doesnt initialise so im struggling to see where im going wrong. They also seem to be formatted the same way.
I tried to google for a WKT String validator, but didnt find one, but i assume it should be ok, as i return multiple other searches with no issues. (i.e. the shapeLine returns a value)
My question is: does this look like a problem in my code, or a possible bug of the library? (i have little faith in my code!)

Xcode 9.4.1 - How to skip remainder of set and move to the next set

While this may not be a good example, but as the question states, I wish to compare randomNo to the sets within numberSets. However, the moment one number is found I want to know if there is a way to skip to the next set.
In summary randomNo contains 2 numbers which can be found in the same set these are "6" and "9". I want to know if the moment I find "6" and can void the rest of the set and move onto the next set without cycling through the rest of the numbers in the set
init() {
let numberSet1 : Set<Int> = [1,2,3,4,5]
let numberSet2 : Set<Int> = [6,7,8,9,10]
let numberSet3 : Set<Int> = [11,12,13,14,15]
let randomNo = [3,6,9,11]
numberSets = [numberSet1,numberSet2,numberSet3]
}
func searchFor(){
for num in randomNo{
for set in numberSets{
if set.contains(num) {
print("The following number was found: ", num)
}
}
}
}
One way to do this is to continue the outer loop:
outer: for num in randomNo{
for set in numberSets{
if set.contains(num) {
print("The following number was found: ", num)
continue outer
}
}
}
Another way is to union all three sets:
let union = numberSet1.union(numberSet2).union(numberSet3)
print(randomNo.filter(union.contains))
First, I think it worth to mention that, in your example the code is not cycling through the sets, rather than arrays of sets (randomNo, numberSets).
If I get the problem right, you do not need to optimize looking up for element in set. Asking whether set contains element or not (a lookup), is not an expensive operation and has complexity of O(1).
If want to stop iterating through the numberSets once first number is found, just use break control flow statement:
func searchFor() {
for num in randomNo {
for set in numberSets {
if set.contains(num) {
print("The following number was found: ", num)
break
}
}
}
}
Hope it helps.

Swift - Why is my application finding nil in this scenario

I have an tableView which loads cells from a xib file. The cells contain 2 labels, 1 shows the quantity and the second shows the price. The quantity is pulled from a static model and works just fine, and the price is pulled from a model which is populated from the result of a URLSession. Below is my cellForRowAt function which works fine in this scenario:
if indexPath.section == 0 {
let item: BasketModel = cellItems[indexPath.row] as! BasketModel
let ordersCell = Bundle.main.loadNibNamed("OrderTableViewCell", owner: self, options: nil)?.first as! OrderTableViewCell
ordersCell.priceLabel.text = item.price
ordersCell.quantityLabel.text = String(basketStruct.getQty(id: item.id!))
return ordersCell
}
My cell shows as follows Qty: 3 Price: 0.70
Now, the problem I have is, when i alter the line above where I set the price label to the following:
ordersCell.priceLabel.text = String(basketStruct.getQty(id: item.id!) * Int(item.price!)!)
I get the error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
What I want, is the qty to be multiplied by the price. However, when I try to use item.price for anything I have to force unwrap it and then I get my error.
How would I go about this ?
It is not that item.price is nil, but Int(item.price!) is nil.
From your question, you said that the price displayed is 0.70, so I suppose item.price must contain the string "0.70".
Well, 0.70 is not a valid Int, so when you try to parse it as an Int, it evaluates to nil.
I think you meant Double(item.price!)!.
As a good practise, you should always check for invalid number strings:
if let price = Double(item.price!) {
// ...
} else {
print("Invalid price: \(item.price!)")
}

Sqlite.Swift: Counting number of rows whose column/field value is "x"

I've been working with Sqlite.Swift for quite a while now and I'm stuck.
I'm trying to get an Int out of the .count of only the amount of rows containing the String value "1" in the column "yes or no".
I've been using the following function to randomly pick a row only once (without repeating). I thought this must be a good start to define the .count for only the described rows but I have absolutely no clue if this'd be possible.
This is how I got my "row randomizer" working:
func randomNumber() -> Int {
var randomNumber = Int(arc4random_uniform(UInt32(try! database.scalar(table.select(ItemId.distinct.count)))))
while pickedNumber == randomNumber {
randomNumber = Int(arc4random_uniform(UInt32(try! database.scalar(table.select(ItemId.distinct.count)))))
}
pickedNumber = randomNumber
return randomNumber
}
let randomRow = randomNumber()
thanks!
Answering my own question:
Simply this did the job:
let count = try! database.scalar(tableName.where(expression == "1").count)
Edit:
You can see the ! here. I did this because I'm sure there is a table where there's a column of that name with cells containing a String value of 1. If you want to go a more secure way use the do / try / catch mechanic.

A better approach to recursion?

I built this code sample in Swift Playgrounds as a proof-of-concept for part of a larger project that I'm working on. What I need to do is pass in a series of options (represented by optionsArray or testArray) where each int is the number of options available. These options will eventually be built into 300+ million separate PDFs and HTML files. The code currently works, and puts out the giant list of possibilities that I want it to.
My question is this: Is there a better approach to handling this kind of situation? Is there something more elegant or efficient? This is not something that will be run live on an app or anything, it will run from a command line and take all the time it needs, but if there is a better approach for performance or stability I'm all ears.
Things I already know: It can't handle a value of 0 coming out of the array. The array is a constant, so it won't happen by accident. The way the code down the line will handle things, 0 is a nonsensical value to use. Each element represents the number of options available, so 2 is essentially a Boolean, 1 would be false only. So if I needed placeholder elements for future expansion, they would be a value of 1 and show up as a 0 in the output.
Also, the final product will not just barf text to the console as output, it will write a file in the permutationEnding() function based on the currentOptions array.
let optionsArray: [Int] = [7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2]
let testArray: [Int] = [7,2,3,2]
var currentOptions: [Int] = []
var outputString: String = ""
func buildPermutations(array: Array<Int>) {
currentOptions.removeAll()
permutationRecursion(array: array, index: 0)
}
func permutationRecursion(array: Array<Int>, index: Int) {
for i in 1 ... array[index] {
currentOptions.append(Int(i-1))
if array.count > (index + 1) {
permutationRecursion(array: array, index: index + 1)
} else {
permutationEnding()
}
currentOptions.removeLast()
}
}
func permutationEnding() {
for i in 1 ... currentOptions.count { // Output Elements
outputString += String(currentOptions[i-1])
}
outputString += "\n" // Goes after output elements closing bracket.
}
// buildPermutations(array: optionsArray)
buildPermutations(array: testArray)
print(outputString)
Thoughts?
I think I've figured out what you're trying to do. You want a string output of every possible integer combination that could map all possible routes on the decision tree.
I got it down to four or five lines.
let n = testArray.count // for readability
let products = ([Int](1...n)).map({testArray[$0..<n].reduce(1, *)})
// products is the cross product of element i + 1 to element n of the array for all i in the array
let zipped = zip(testArray, products)
for i in 0..<testArray.reduce(1, *) { // this reduce is the cross product of the whole array
let treePath = zipped.map(){ String(i / $0.1 % $0.0) }.joined()
outputString += treePath + "\n"
}
One more edit: I think this might be faster with some fancy matrix operations like NumPy. I wonder if the Accelerate framework could do some magic for you, but I have not worked with it.
edit: I was curious so I timed it with this test array
let testArray: [Int] = [7,2,2,2,2,2,2,3,2]
The recursive function in the question was: 132.56 s
The zip-map here was: 14.44 s
And it appears to be exponential as I add elements to the test array.