0

I've tried a lot of approaches to randomly generate an array from existing one. And one of them finally worked out for me:

    extension Array {
    mutating func shuffle() {
// get data from my FireBase and calculate amount of items in it
        var ref: DatabaseReference?
        var databaseHandle: DatabaseHandle?
        var words = [lWord]()
        ref = Database.database().reference()
            guard let uid = Auth.auth().currentUser?.uid else {
                print ("smt wrong with user uid")
                return
            }
           databaseHandle = ref?.child("Users").child(uid).child("LearningNow").observe(.value, with: { (snapshot) in
                var newItems: [lWord] = []
                for item in snapshot.children {
                    let wordItem = lWord(snapshot: item as! DataSnapshot)
                    newItems.append(wordItem)
                }
                words = newItems
            })
        let count = words.count + 1
        for _ in 0..<count  {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}

But, for some reasons, this code works only if I put this method on the array inside of the button-action, for example:

@IBAction func generate(_ sender: UIButton) {
    words.shuffle()
    print (words)
}

If put exactly the same code in the viewDidLoad, nothing is sorted. So how can I sort my array without any action?

P.S. If you don't know the answer, you can recommend any other approach to generate random array. Thank You!

Oleg Blanutsa
  • 82
  • 1
  • 6
  • You don't see `"smt wrong with user uid"` printout, do you? – Sergey Kalinichenko Aug 05 '17 at 19:21
  • No, I don't. Firebase works fine – Oleg Blanutsa Aug 05 '17 at 19:22
  • The most likely problem is that the changes performed in `viewDidLoad` get written over by code that executes later. See if putting the same code into `viewWillAppear` fixes the problem. – Sergey Kalinichenko Aug 05 '17 at 19:23
  • No, it also doesn't work. Maybe the problem is that I retrieve the same data from FireBase twice? The first time in the ViewDidLoad, and the second in the extension, otherwise I don't know how to constraint for loop there, because the number of items in the array can be different . – Oleg Blanutsa Aug 05 '17 at 19:40
  • Try putting the `for _ in` loop inside the `.observe`'s completion handler, right below `words = newItems` – RPatel99 Aug 05 '17 at 21:04

1 Answers1

0

Thank you for all your replies! I found the solution, I had to replace my method (code is from this question):

extension Array {
/// Returns an array containing this sequence shuffled
var shuffled: Array {
    var elements = self
    return elements.shuffle()
}
/// Shuffles this sequence in place
@discardableResult
mutating func shuffle() -> Array {
    indices.dropLast().forEach {
        guard case let index = Int(arc4random_uniform(UInt32(count - $0))) + $0, index != $0 else { return }
        swap(&self[$0], &self[index])
    }
    return self
}
var chooseOne: Element { return self[Int(arc4random_uniform(UInt32(count)))] }
func choose(_ n: Int) -> Array { return Array(shuffled.prefix(n)) }
}

As you can see, I don't retrieve data from FireBase for this approach. So, maybe the problem was there.

Oleg Blanutsa
  • 82
  • 1
  • 6