Не удается подписать значение типа «[UInt32]»

У меня есть массив чисел, которые были сгенерированы случайным образом, и затем я пытаюсь запросить Firebase для вопроса, который равен значению с индексом [0] в массиве выбранных чисел. Проблема на данный момент в том, что я получаю ошибку Cannot subscript a value of type '[UInt32]'. P.S. Я не очень разбираюсь в Swift, поэтому точные кодовые решения будут очень признательны! Я также прикрепил свою структуру firebase...

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-данные:

{
  "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
  }
}

person Tom Fox    schedule 27.02.2016    source источник
comment
@FrankvanPuffelen готово. Я знаю, это выглядит немного странно, но это единственный способ, которым мне удалось это сделать. Имейте в виду, что вопросы - это просто фиктивные вопросы :)   -  person Tom Fox    schedule 27.02.2016
comment
Идеальный. Спасибо за правки. Очистка комментариев...   -  person Frank van Puffelen    schedule 27.02.2016


Ответы (1)


Это типичная ситуация, когда компилятор Swift скрывает реальную ошибку за другой. Метод .queryEqualToValue(..) ожидает аргумент типа AnyObject; который может содержать только ссылочные (классовые) типы, тогда как UInt32 является типом значения.

Другой причиной путаницы может быть то, что мы обычно привыкли к тому факту, что AnyObject типы могут, на первый взгляд, содержать Int типы, тогда как на самом деле такие присваивания неявно преобразуют собственный тип значения Swift Int в Foundation __NSCFNumber ссылочный тип. Однако это неявное преобразование недоступно для типа UInt32.

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] */

Следовательно, вы можете решить эту проблему следующим образом:

  1. Пусть selectedNumbers будет массивом 0f Int, а не UInt32 (и соответствующим образом измените затронутые части вашего кода).

  2. Выполните преобразование типа из UInt32 в Int в вызове .queryEqualToValue(..). Например, в приведенном выше примере:

    a = Int(bar[0])
    

    Просто обратите внимание, что для 32-битных систем (например, iPhone 5) половина верхнего диапазона чисел, представляемых типом UInt32, не может быть представлена ​​типом Int, поскольку в 32-битной системе Int соответствует Int32.

    INT32_MAX   // 2147483647
    UINT32_MAX  // 4294967295
    

    Однако при беглом взгляде на ваш код не кажется, что здесь это должно быть проблемой, так как элементы selectedNumbers не будут содержать больших чисел, представляемых UInt32 (и для 64-битных систем: ОК, поскольку Int соответствует Int64). Тем не менее, если вы выберете этот вариант, вам следует, в качестве хорошей практики, подтвердить перед преобразованием, что значение UInt32 может быть представлено типом Int в системах, предназначенных для запуска вашего приложения.

person dfrib    schedule 27.02.2016
comment
@TomFox Рад помочь. - person dfrib; 27.02.2016