could not find member subscript - ios

I am trying to execute the following code and getting the error Could not find member 'subscript on Xcode6
var b:[[Float]] = [[1,2]]
var i2 = 0 // second to last control point
var pointIm1 = CGPoint(x: 0.0,y: 0.0)
var pointI = CGPoint(x: 0.0,y: 0.0)
var pointIp1 = CGPoint(x: 0.0,y: 0.0)
var px:Float = b[0][0] * Float(pointIm1.x) + b[0][0] * Float(pointI.x) + b[0][0] + b[0][0] * Float(pointIp1.x)
Anyone has idea why is giving error
Edit: Do anyone have better idea or i need to create different variables for each subscript as Nate suggested in his answer
//not looks good
var bj0 = b[j][0]
var bj1 = b[j][1]
var bj2 = b[j][2]
var bj3 = b[j][3]
var px:Float = bj0 * Float(pointIm1.x) + bj1 * Float(pointI.x) + bj2 + bj3 * Float(pointIp1.x)

It isn't a problem with the subscript - Swift gets into trouble when trying to parse longer multi-item expressions like your final line. In a playground I get this error:
expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
You'll need to refactor that line to get past this limitation - something like:
let b00 = b[0][0]
var px: Float = b00 * Float(pointIm1.x) + b00 * Float(pointI.x) + b00 + b00 * Float(pointIp1.x)
You could probably just break it up into two steps, like this:
var px:Float = bj0 * Float(pointIm1.x) + bj1 * Float(pointI.x)
px += bj2 + bj3 * Float(pointIp1.x)

It looks like a compiler bug. I tried this expression (obtained from yours, and removing all multiplications):
var px:Float = b[0][0] + b[0][0] + b[0][0] + b[0][0]
and it fails, whereas this:
var px:Float = b[0][0] + b[0][0] + b[0][0]
works.
So Nate Cook's answer is correct, it's the compiler getting into trouble.
More tests - using a unidimensional array, this works:
var c:[Float] = [1.0, 2.0]
var px2: Float = c[0] + c[0] + c[0] + c[0] + c[0]
but this doesn't
var px2: Float = c[0] + c[0] + c[0] + c[0] + c[0] + c[0] // Cannot invoke '+' with arguments of type '($T28, $T32)'
Note that your expression can be refactored as:
var px:Float = b[0][0] * (Float(pointIm1.x) + Float(pointI.x) + 1.0 + Float(pointIp1.x))

Related

Swift The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

Following is method from a library in my project
public convenience init(hueRotate: Double) {
let c = cos(hueRotate)
let s = sin(hueRotate)
let m1 = [0.213, 0.715, 0.072,
0.213, 0.715, 0.072,
0.213, 0.715, 0.072]
let m2 = [0.787, -0.715, -0.072,
-0.213, 0.285, -0.072,
-0.213, -0.715, 0.928]
let m3 = [-0.213, -0.715, 0.928,
0.143, 0.140, -0.283,
-0.787, 0.715, 0.072]
let a = { i in
m1[i] + c * m2[i] + s * m3[i]
}
self.init(values: [a(0), a(1), a(2), 0, 0,
a(3), a(4), a(5), 0, 0,
a(6), a(7), a(8), 0, 0,
0, 0, 0, 1, 0])
}
on this following part of code I am getting compiler error saying The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
let a = { i in
m1[i] + c * m2[i] + s * m3[i]
}
How to fix this?
It should be enough to tell the compiler what a returns so change the declaration to
let a = { (i) -> Double in
m1[i] + c * m2[i] + s * m3[i]
}
Swift is having a problem with your equation being too long in the closure of var a. Try splitting the expression into smaller ones, like this:
let a = { i in
c * m2[i]
}
let b = { i in
s * m3[i]
}
let c = { i in
m1[i]
}
self.init(values: [a(0) + b(0) + c(0),
a(1) + b(1) + c(1),
a(2) + b(2) + c(2),
0, 0,
a(3) + b(3) + c(3),
a(4) + b(4) + c(4),
a(5) + b(5) + c(5),
0, 0,
a(6) + b(6) + c(6),
a(7) + b(7) + c(7),
a(8) + b(8) + c(8),
0, 0, 0, 0, 0, 1, 0])

How can I change the Double value in my dictionary outside the function?

var grades: [String : Double]
grades = ["A": 0.0, "A-": 0.0, "B+": 0.0, "B": 0.0, "B-": 0.0, "C+": 0.0, "C": 0.0, "C-": 0.0, "D+": 0.0, "D": 0.0, "D-": 0.0, "F": 0.0]
func calcGPA() {
if let a = grades["A"], amin = grades["A-"], bplu = grades["B+"], b = grades["B"], bmin = grades["B-"], cplu = grades["C+"], c = grades["C"], cmin = grades["C-"], dplu = grades["D+"], d = grades["D"], dmin = grades["D-"], f = grades["F"] {
// Divide by this
let gradesAdded = a + amin + bplu + b + bmin + cplu + c + cmin + dplu + d + dmin + f
//grades multiplied by their values and added ex. a * 4.0 + amin * 3.7
let gradesCalculated = a * 4.0 + amin * 3.7 + bplu * 3.3 + b * 3.0 + bmin * 2.7 + cplu * 2.3 + c * 2.0 + cmin * 1.7 + dplu * 1.3 + d * 1.0 + dmin * 0.7 // Dont do F because it would just add 0
var gpa = gradesCalculated / gradesAdded
if gpa.isNaN {
gpa = 0.0
}
}
}
Is there a way to do something like grades["A"] += 1.0 so that it goes up by one and I can call calcGPA()? I can't figure out how to make this work. Any help on this would be awesome
You can increase a value in your dictionary by force unwrapping the lookup:
grades["A"]! += 1.0
but this is dangerous because it will crash if the key isn't in the dictionary. So, you should check:
if let count = grades["A"] {
grades["A"] = count + 1
}
Here is an updated version of your program:
func calcGPA(_ termGrades: [String]) -> Double? {
var grades: [String: Double] = ["A": 0.0, "A-": 0.0, "B+": 0.0, "B": 0.0, "B-": 0.0, "C+": 0.0, "C": 0.0, "C-": 0.0, "D+": 0.0, "D": 0.0, "D-": 0.0, "F": 0.0]
var gpa: Double?
for grade in termGrades {
if let count = grades[grade] {
grades[grade] = count + 1
} else {
print("Hmmm, \(grade) is not a valid value for a grade")
return nil
}
}
if let a = grades["A"], amin = grades["A-"], bplu = grades["B+"], b = grades["B"], bmin = grades["B-"], cplu = grades["C+"], c = grades["C"], cmin = grades["C-"], dplu = grades["D+"], d = grades["D"], dmin = grades["D-"], f = grades["F"] {
// Divide by this
let gradesAdded = a + amin + bplu + b + bmin + cplu + c + cmin + dplu + d + dmin + f
//grades multiplied by their values and added ex. a * 4.0 + amin * 3.7
let gradesCalculated = a * 4.0 + amin * 3.7 + bplu * 3.3 + b * 3.0 + bmin * 2.7 + cplu * 2.3 + c * 2.0 + cmin * 1.7 + dplu * 1.3 + d * 1.0 + dmin * 0.7 // Dont do F because it would just add 0
gpa = gradesAdded == 0 ? nil : gradesCalculated / gradesAdded
}
return gpa
}
// example calls
calcGPA(["E"]) // nil "Hmmm, E is not a valid value for a grade"
calcGPA(["A-"]) // 3.7
calcGPA(["A", "B"]) // 3.5
calcGPA(["B", "B+", "A-"]) // 3.333333333333333
calcGPA([]) // nil
Notes:
I changed your function to take an array of grades and return a Double? (Optional Double).
nil is returned if anything goes wrong (input array is empty, input array contains invalid grade such as "E").
Divide by zero is avoided ahead of time by checking the divisor before the calculation.
Alternate Solution:
And now for something completely different...
Inspired by #CodeBender's comment, here is an implementation that uses an enum with an associated value to represent the grades:
enum Grade: Double {
case A = 4.0
case Aminus = 3.7
case Bplus = 3.3
case B = 3.0
case Bminus = 2.7
case Cplus = 2.3
case C = 2.0
case Cminus = 1.7
case Dplus = 1.3
case D = 1.0
case Dminus = 0.7
case F = 0
}
func calcGPA(_ termGrades: [Grade]) -> Double? {
if termGrades.count == 0 {
return nil
} else {
let total = termGrades.reduce(0.0) { (total, grade) in total + grade.rawValue }
return total / Double(termGrades.count)
}
}
// example calls
calcGPA([.A, .B]) // 3.5
calcGPA([.B, .Bplus, .Aminus]) // 3.3333333333
calcGPA([.A, .A, .Bplus]) // 3.7666666666
calcGPA([.F, .F, .F]) // 0
calcGPA([]) // nil

swift- get exc_bad_instruction (code=exc_i386_invop, subcode=0x0) with array value replacement in while loop

I am making a note writing app. In this app I am turning the lines into a bezier curve. At the moment I am getting an error when I try to put new values into a matrix that was defined outside of the while loop. I have tried the expression by itself when put into a dummy variable and it works in the loop. When I use the format for replacing a value of the two dimensions variable it works outside the loop, however, when I do both those actions together in the loop it does not work.
//: Playground - noun: a place where people can play
import UIKit
var x2 = 6.0
var y2 = 5.0
var x1 = 1.0
var y1 = 1.0
var p1x = 2.0
var p1y = 3.0
var B = 6.5
var Ba = 2.2
var percentall = Ba/B
var yall = 5.0
var xall = 1.0
var A = 4.0
var C = 5.0
var Ct = 0.0
var At = 0.0
var Aall = Int(A) * 10
var Call = Int(C) * 10
var thelistx = [[Double]](count: Call, repeatedValue: [Double](count: Call, repeatedValue: 0.0 ))
var thelisty = Array(count: Aall, repeatedValue: Array(count: Call, repeatedValue: 0.0 ))
var theAt = 0
var theCt = 0
while At <= A {
var Apercent = percentall * At
var Aend = y1 + At
var yslope = (A - At) * percentall + Aend
var lefty = (yslope - Apercent) * percentall + Apercent
var righty = ( y2 - yslope) * percentall + yslope
while Ct <= C {
var Cpercent = percentall * Ct
var Cend = x2 - Ct
var xslope = (C - Ct) * percentall + Cend
var leftx = (xslope - x1) * percentall + x1
var rightx = (x2 - xslope) * percentall + xslope
thelistx [theAt] [theCt] = (rightx - leftx) * percentall + left
*********************Execution was interrupted, reason exc_bad_instruction (code=exc_i386_invop, subcode=0x0) ***************
thelisty [theAt] [theCt] = (righty - lefty) * percentall + lefty
Ct += 0.1
theCt += 1
}
At = At + 0.1
theAt += 1
}
The console shows what your error is:
fatal error: Index out of range
You're going out of bounds with thelistx [theAt] [theCt]
Changing while Ct < C to Ct < C - 1 keeps your calls in the bounds of the array.

Cannot Invoke '^' with an argument list of type '($T27, IntegerLiteralConvertible)'

func FindDistance(currentLatitude: Double, currentLongtitude: Double, compareLatitude: Double, compareLongtitdue: Double) -> Double {
var dlon = compareLongtitdue - currentLongtitude
var dlat = compareLatitude - currentLatitude
let WorldRadius = 6371
var a = sin(dlat/2)^2 + cos(currentLatitude) * cos(compareLatitude) * sin(dlon/2)^2
var c = 2 * atan2(sqrt(a), sqrt(1-a))
var d = WorldRadius * c
}
println(FindDistance(11.583431, 104.920141, 11.584966, 104.918569))
There is an Error in Line in Variable "a". said 'Cannot Invoke '^' with an argument list of type '($T27, IntegerLiteralConvertible)'.
I guess you want to use pow(x,y) function which returns x raised to the power of y.
So in order to access this function you need to import Darwin first and rewrite code as follow:
import Darwin
func FindDistance(currentLatitude:Double, currentLongtitude:Double, compareLatitude:Double, compareLongtitdue:Double) -> Double {
var dlon = compareLongtitdue - currentLongtitude
var dlat = compareLatitude - currentLatitude
let WorldRadius: Double = 6371
var a = pow(sin(dlat/2), 2) + cos(currentLatitude) * cos(compareLatitude) * pow(sin(dlon/2),2)
var c = 2 * atan2( sqrt(a), sqrt(1-a) )
var d = WorldRadius * c
return d
}

UInt8 is not convertible to CGFloat error in iOS Swift

I am a beginner level programmer in iOS app development using Swift. Now I am facing the compile time issue "UInt8 is not convertible to CGFloat"
var numberOfAvatars:Int = 8
let count:Int = 1
let columns:Int = 3
let dimension:CGFloat = 84.0
var spacing:CGFloat = (avatarContentcroll.frame.size.width - columns * dimension)/(columns+1)
var scHeight:CGFloat = spacing + (numberOfAvatars/columns) * (dimension + spacing)
I've tried all the solutions out there and did many experiments. And I am not sure why still I am getting this error.
You have to do it explicitly as
var spacing:CGFloat = CGFloat((avatarContentcroll.frame.size.width) - CGFloat(columns) * (dimension))/(columns+1)
var scHeight:CGFloat = CGFloat(spacing + (CGFloat(numberOfAvatars)/CGFloat(columns)) * (dimension + spacing))
or you can try converting every expression in CGFloat
var spacing:CGFloat = ((avatarContentcroll.frame.size.width) - CGFloat(columns) * (dimension))/(columns+1)
var scHeight:CGFloat = spacing + (CGFloat(numberOfAvatars)/CGFloat(columns)) * (dimension + spacing)
You must explicitly cast your Ints as CGFloats (via as), or construct them -- like so:
var spacing:CGFloat = ((avatarContentcroll.frame.size.width) - CGFloat(columns) * (dimension))/(columns+1)
var scHeight:CGFloat = spacing + (CGFloat(numberOfAvatars)/CGFloat(columns)) * (dimension + spacing)

Resources