Hi I'm trying to shuffle an array which I can then use in all my IBAction functions thereafter in the order that I shuffled them. Example of code which is the same idea as what I have...
Class ViewContoller: UIViewContoller
Let numbers = [1,2,3,4,5]
override func viewDidLoad() {
super.viewDidLoad() }
I've tried to write a function here to create an array which has been shuffled so I can use that shuffled array ...
func shuffledArray() -> Array<Int> {
let numbersArray = numbers.shuffled()
return numbersArray }
let myListOfShuffledNumbers = shuffledArray()
Now this works in playground.. but when I try this my viewcontroller.swift I get error 'cannot use instance member 'shuffledArray' within property initializer; property initializers run before self is available.
So I know if I'm in a IBAction func I can run the function let shuffledNumbers = shuffledArray()and get an Array of shuffled numbers to use but my problem is I need to use that same shuffle order in another IBAction function. So how can I make a universal array of shuffled numbers to use anywhere on my view controller.
I've tried lazy var myListOfShuffledNumbers = shuffledArray()
This gets rid of my error but it doesn't help me because I get a 2 different list order when I use 'myListOfShuffledNumbers' in 2 different IBAction functions
What can I do ?? Thanks
You can define a property that you can access from anywhere in your ViewContoller, like this:
class ViewContoller: UIViewContoller {
let unshuffledNumbers = [1,2,3,4,5]
var myListOfShuffledNumbers = [Int]() /// here! it's still empty at first
#IBAction func firstButtonPressed(_ sender: Any) {
myListOfShuffledNumbers = unshuffledNumbers.shuffled()
}
#IBAction func secondButtonPressed(_ sender: Any) {
/// do something with myListOfShuffledNumbers here...
}
}
At first, myListOfShuffledNumbers is still an empty array of Ints. But inside your first IBAction, you can assign that to unshuffledNumbers.shuffled(). Then, you can access it from inside your second IBAction.
Also it might be easier to just write [Int] instead of Array<Int> -- they are the same thing.
func shuffledArray() -> [Int] {
let numbersArray = numbers.shuffled()
return numbersArray
}
If you want an array that is shuffled then just convert it to a set. Sets will not keep the original order of the array.
Related
I have built the following "helper" function, which takes as parameters:
'unsortedArray': The array of Venue objects required to be sorted by its .venueID string property
'sortingGeoArray': the Geofire string keys to be used as reference to order the unsorted array above.
and it returns a sorted array of type [Venue] via an escaping handler.
I have tried to implement this nice and simple solution suggested on the following thread:
'Sorting a Swift array by ordering from another array'
func sortVenuesArraybyGeofireKeys(unsortedArray: [Venue], sortingGeoArray: [String] , handler: #escaping (_ sortedArray: [Venue]) -> ()){
let ordering = Dictionary(uniqueKeysWithValues: sortingGeoArray.enumerated().map { ($1, $0) })
let sorted: [Venue] = unsortedArray.sorted{ ordering[$0.venueID]! < ordering[$1.venueID]! }
handler(sorted)
}
I have tried the sorting code above in multiple places through out my code by I always get a "Unexpectedly found nil while unwrapping an Optional value" at the following line (works when i test it an playground):
let sorted: [Venue] = unsortedArray.sorted{ ordering[$0.venueID]! < ordering[$1.venueID]!
On my debug window below, I have a feeling that the .map function into the let 'ordering' is not working and therefore finding nil on the next line
any help would be appreciated.
UPDATE: thanks to the support below, it appears that my Geofire query below in particular the 'append' to venueGeoKeys [string] array is not appending the key values, hence why found nil when I execute the function to sort.
let query = self.GEOFIRE_VENUES.query(at: location, withRadius: 1000)
query.observe(.keyEntered) { (key: String!, location: CLLocation!) in
self.venueGeoKeys.append(key)
}
for tempExportData in exportDataArray {
let tmpRegNO:NSString = (tempExportData as AnyObject).object(forKey: kRegisteredNo) as! NSString
print("tmpRegNO is",tmpRegNO)
var tmpNoArray:Array = [String]()
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
I am trying to add string value i.e tmpRegNO to the Array tmpNoArray.
In this I can able to add only one value to the array at a time.
How to add the next value to that array when it is looping for second time.
As already mentioned you have to declare the array before entering the loop.
Your code is very objectivecish. This is a swiftier version. Don't annotate types the compiler can infer and use key subscription rather than ugly casting to AnyObject and objectForKey:.
var tmpNoArray = [String]()
for tempExportData in exportDataArray {
let tmpRegNO = tempExportData[kRegisteredNo] as! String
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
You can even write the whole expression in one line:
let tmpNoArray = exportDataArray.flatMap { $0[kRegisteredNo] as? String }
You need move the tempNoArray initialization outside of your for in loop, if not the your array will be initialized once for every item in your exportDataArray remaining only the las item as consequence
You need something like this
var tmpNoArray:Array = [String]()
for tempExportData in exportDataArray{
if let tmpRegNO = tempExportData[kRegisteredNo] as? String
{
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
}
var pickerData: [[String]] = [String]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Connect data:
self.gothramPicker.delegate = self
self.gothramPicker.dataSource = self
pickerData = [
[["A"],["i","ii","iii"]],
[["B"],["iv","v","vi","vii"]]
]"
getting error of Contextual type 'String' cannot be used with array literal.
my picker has two sections and each item if selected in the first picker has its own subdivisions to select from the second picker.
I want to use Array in Array and each main array has subarrays of different list. When I select first array in the picker it should show only the subitems of the particular Array item. For which when I add the double Brackets, I am getting the error. Also please let me know any error in the code
#sureshtrb , I am not posting answer because you don't asked question here. Frankly, you are troubling in Syntax understanding only.
You were declaring picketData of type Array([]) that contains array of string[[String]], and by putting ["A"] in place of string, you are adding an array ["A"] in place of String "A".
As per your real problem, I suggest you to go with 2 diff array or use dictionary.
The below code compiles.
var pickerData: [[String]] = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
pickerData = [
["A","i","ii","iii"],
["B","iv","v","vi","vii"]
]
}
I want to pass an array of strings through segue, but my app crashes. Here is what I have in the starting ViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "sendToOther") {
let svc = segue.destinationViewController as! OtherMinerals;
svc.toPass1 = String(DataSet[0])
svc.toPass2 = String(DataSet[1])
and this is what I have in the receiving ViewController
var toPass:String!
var toPass2:String!
so, I am passing every item separately through segue, but that's not elegant. I'd like to pass the whole array through, but for some reason I can't get the code right. Any genius out there to assist??
Just create a [DataSet] variable in your second ViewController and pass your whole DataSet array to your second ViewController instead of the two strings:
//second viewcontroller:
var dataSetArray:[DataSet]
//first viewcontroller:
svc.dataSetArray = yourDataSet
Change the type of the variable "toPass" to be [String]. If your DataSet is of the same type you can pass the array like so
svc.toPass = DataSet
There are several posts on SO like this, and the only solution suggested that would seem to work is manually removing and inserting a property at the same index.
But this feels messy, and some posts suggest it's possible in Xcode 7 to directly update dictionary properties if inside an array of dictionaries.
However, it's not working for the code below, generating the Cannot assign to immutable expression of type [String:AnyObject] error.
// Class vars
var userDict = [String:AnyObject]()
var accounts = [[String:AnyObject]]()
func setHistory(index: Int, history: [String]) {
(userDict["accounts"] as! [[String:AnyObject]])[index]["history"]! = history
(userDict["accounts"] as! [[String:AnyObject]])[index]["history"] = history
userDict["accounts"][index]["history"] = history
userDict["accounts"][index]["history"]! = history
}
All four lines inside of setHistory try to do the same thing, and all fail.
Right now the way you are doing this:
userDict["accounts"] as! [[String:AnyObject]])[index]["history"]
you are working with an immutable container.
You are going to have to design it like this:
func setHistory(index: Int, history: [String]) {
//this line copies from user dict, it is not a pointer
var account = userDict["accounts"] as! [[String:AnyObject]];
//this line sets the new history
account[index]["history"] = history;
//this line will update the dictionary with the new data
userDict["accounts"] = account
}
I think you are better off with a class to model your data.
Anyhow, you can call an old friend from ObjC, NSMutableDictionary:
var userDict = [String: AnyObject]()
var accounts = [NSMutableDictionary]()
accounts.append(["history": ["history1.1", "history1.2"]])
accounts.append(["history": ["history2.1", "history2.2"]])
userDict["accounts"] = accounts
func setHistory(index: Int, history: [String]) {
userDict["accounts"]![index].setObject(history, forKey: "history")
}
setHistory(0, history: ["history1.1", "history1.2", "history1.3"])
print(userDict)