I have an array of numbers that have been generated randomly and I am then trying to query Firebase for a question that is equal to the value at index [0] in the array of chosen numbers. The problem at the moment is that I get an error Cannot subscript a value of type '[UInt32]'
. P.S. I am not extremly experienced in swift so exact code solutions would be very apreciated! I have also attached my firebase structure...
import UIKit
import Firebase
class QuestionViewController: UIViewController {
let ref = Firebase(url: "https://123test123.firebaseio.com/questions")
override func viewDidLoad() {
super.viewDidLoad()
// An empty array to hold the selected numbers
var selectedNumbers: [UInt32] = []
// A range of acceptable numbers
let randomNumberRange = 1...10
// How many numbers are needed?
let randomNumbersToChoose = 10
// Crash if asking for more numbers than are available in the range
assert(randomNumberRange.count >= randomNumbersToChoose, "Must have enough numbers to choose from!")
// Repeat this loop until all enough numbers have been selected
while selectedNumbers.count < randomNumbersToChoose {
// Pick a random number within the allowed range
let selectedNumber = arc4random_uniform(UInt32(randomNumberRange.endIndex - randomNumberRange.startIndex)) + UInt32(randomNumberRange.startIndex)
// If it's not already in the selected array, add it
if (selectedNumbers.indexOf(selectedNumber) == nil) {
selectedNumbers.append(selectedNumber)
}
}
// Print the result
print(selectedNumbers)
print(selectedNumbers)
let selectedNumberIndex: UInt32 = 2
ref.queryOrderedByChild("value").queryEqualToValue(selectedNumbers[0])
.observeEventType(.ChildAdded, withBlock: {
snapshot in
//Do something with the question
print(snapshot.key)
print(snapshot.value.valueForKey("question"))
})
}
@IBAction func truepressed(sender: AnyObject) {
}
@IBAction func falsePressed(sender: AnyObject) {
}
}
JSON data:
{
"question1" : {
"answer" : "Nohghpe",
"question" : "Do you know swift",
"value" : 1
},
"question10" : {
"answer" : "A fdsbit",
"question" : "Do you kndfggow firebase",
"value" : 10
},
"question2" : {
"answer" : "A bfhit",
"question" : "Dodhfg you know firebase",
"value" : 2
},
"question3" : {
"answer" : "A bsdit",
"question" : "Do you know firebsgdfase",
"value" : 3
},
"question4" : {
"answer" : "A vcxbit",
"question" : "Do yosgfdu know firebase",
"value" : 4
},
"question5" : {
"answer" : "A bivcxt",
"question" : "Do you kfghnow firebase",
"value" : 5
},
"question6" : {
"answer" : "A bxcvit",
"question" : "Do you know fnhirebase",
"value" : 6
},
"question7" : {
"answer" : "A bivxct",
"question" : "Do you sgdfknow firebase",
"value" : 7
},
"question8" : {
"answer" : "A bivcxt",
"question" : "Do you knsfdow firebase",
"value" : 8
},
"question9" : {
"answer" : "A bdsfit",
"question" : "Do you kdfgnow ffsdirebase",
"value" : 9
}
}
This is a typical situation of the Swift compiler obscuring the real error behind another one. The .queryEqualToValue(..)
method expects an argument of type AnyObject
; which can hold only reference (class) types, whereas UInt32
is a value type.
Another subject of confusion could be that we're generally used to the fact that AnyObject
types can, seemingly, hold Int
types, when in fact such assignments implicitly converts the Swift native Int
value type to the Foundation __NSCFNumber
reference type. This implicit conversion is, however, not available for UInt32
type.
var a : AnyObject?
let foo : [Int] = [1, 2, 3]
let bar : [UInt32] = [1, 2, 3]
/* OK: Int -> [implicitly] -> __NSCFNumber */
a = foo[0]
print(a!.dynamicType) // __NSCFNumber
/* Not OK */
a = bar[0]
/* error: cannot subscript a value of type '[UInt32]' a = bar[0] */
Hence, you could solve this issue by:
Letting selectedNumbers
be an array 0f Int
, rather than UInt32
(and modify the affected parts of your code accordingly).
Perform a type conversion from UInt32
to Int
in your call to .queryEqualToValue(..)
. E.g., in the example above:
a = Int(bar[0])
Just take care that for 32-bit systems (e.g. iPhone 5), half the upper range of numbers representable by UInt32
type cannot be represented by Int
type, since on 32-bit system, Int
corresponds to Int32
.
INT32_MAX // 2147483647
UINT32_MAX // 4294967295
From a quick glance at your code, however, it doesn't seem as if this should be an issue here, as the elements of selectedNumbers
will not contain the larger numbers representable by UInt32
(and, for 64-bit systems: OK, as Int
corresponds to Int64
). If choosing this option, you should, however, for good practice, assert prior to conversion that the UInt32
value can be represented by the Int
type on the systems intended to run your application.