Random array string getting nil - ios

I am using the random range function to my array string. Also I am using a filter to not repeat to my array string, but sometimes my first random string is nil.
Random range code:
func randomNumber(range: Range<Int> = 1...6) -> Int {
let min = range.startIndex
let max = range.endIndex
return Int(arc4random_uniform(UInt32(max - min))) + min
}
I'm getting nil from the firstItem:
var a = cities[randomNumber(0...80)]
if Marmara.contains(a){
firstItem = a
print(firstItem) //It's getting nil sometimes.
var filteredForSecond = Marmara.filter{$0 != firstItem}
secondItem = filteredForSecond[randomNumber(0...filteredForSecond.count-1)]
print(secondItem)
var filteredForThird = Marmara.filter{$0 != secondItem && $0 != firstItem}
thirdItem = filteredForThird[randomNumber(0...filteredForThird.count-1)]
print(thirdItem)
var filteredForFourth = Marmara.filter{$0 != thirdItem && $0 != secondItem && $0 != firstItem}
print(fourthItem)
fourthItem = filteredForFourth[randomNumber(0...filteredForFourth.count-1)]
//sehirler.removeAtIndex(s)
print("\(firstItem), \(secondItem), \(thirdItem), \(fourthItem)")
}
I have an "81" string in the array using this code. What should I do to fix this nil string problem?

I would at least make the following change. See if this fixes the problem.
var a = cities[randomNumber(0...cities.count-1)]

I solved the problem. I'm checking if it is nil, taking again random string and it's not getting nil anymore.
Here is the working code:
var a = cities[randomNumber(0...cities.count-1)]
while a.isEmpty{
a = cities[randomNumber(0...cities.count-1)]
}
if Marmara.contains(a) && a != ""{
firstItem = a
if firstItem.isEmpty{
print("nil")
}
print(firstItem)
var filteredForSecond = Marmara.filter{$0 != firstItem}
secondItem = filteredForSecond[randomNumber(0...filteredForSecond.count-1)]
print(secondItem)
var filteredForThird = Marmara.filter{$0 != secondItem && $0 != firstItem}
thirdItem = filteredForThird[randomNumber(0...filteredForThird.count-1)]
print(thirdItem)
var filteredForFourth = Marmara.filter{$0 != thirdItem && $0 != secondItem && $0 != firstItem}
print(fourthItem)
fourthItem = filteredForFourth[randomNumber(0...filteredForFourth.count-1)]
//sehirler.removeAtIndex(s)
print("\(firstItem), \(secondItem), \(thirdItem), \(fourthItem)")
}

Related

How can I guarantee that a Swift closure (referencing Firebase) fully executes before I move on?

I have multiple query snapshots with closures and some of them are using the data supplied by the query that came before it.
I have read up on GCD and I've tried to implement a DispatchGroup with .enter() and .leave() but I am apparently doing something wrong.
If somebody can help me by laying out exactly how to force one task to be performed before another, that would solve my problem.
If you can't tell, I am somewhat new to this so any help is greatly appreciated.
//MARK: Get all userActivities with distance(All Code)
static func getAllChallengesWithDistanceAllCode(activity:String, completion: #escaping ([Challenge]) -> Void) {
let db = Firestore.firestore()
let currUserID = Auth.auth().currentUser!.uid
var currUserName:String?
var distanceSetting:Int?
var senderAverage:Double?
var senderBestScore:Int?
var senderMatchesPlayed:Double?
var senderMatchesWon:Double?
var senderWinPercentage:Double?
var validUserActivities = [Challenge]()
db.collection("users").document(currUserID).getDocument { (snapshot, error) in
if error != nil || snapshot == nil {
return
}
currUserName = snapshot?.data()!["userName"] as? String
distanceSetting = snapshot?.data()!["distanceSetting"] as? Int
}
db.collection("userActivities").document(String(currUserID + activity)).getDocument { (snapshot, error) in
//check for error
//MARK: changed snapshot to shapshot!.data() below (possible debug tip)
if error != nil {
//is error or no data..??
return
}
if snapshot!.data() == nil {
return
}
//get profile from data proprty of snapshot
if let uActivity = snapshot!.data() {
senderBestScore = uActivity["bestScore"] as? Int
senderMatchesPlayed = uActivity["played"] as? Double
senderMatchesWon = uActivity["wins"] as? Double
senderAverage = uActivity["averageScore"] as? Double
senderWinPercentage = round((senderMatchesWon! / senderMatchesPlayed!) * 1000) / 10
}
}
if distanceSetting != nil {
db.collection("userActivities").whereField("activity", isEqualTo: activity).getDocuments { (snapshot, error) in
if error != nil {
print("something went wrong... \(String(describing: error?.localizedDescription))")
return
}
if snapshot == nil || snapshot?.documents.count == 0 {
print("something went wrong... \(String(describing: error?.localizedDescription))")
return
}
if snapshot != nil && error == nil {
let uActivitiesData = snapshot!.documents
for uActivity in uActivitiesData {
let userID = uActivity["userID"] as! String
UserService.determineDistance(otherUserID: userID) { (determinedDistance) in
if determinedDistance! <= distanceSetting! && userID != currUserID {
var x = Challenge()
//Sender
x.senderUserID = currUserID
x.senderUserName = currUserName
x.senderAverage = senderAverage
x.senderBestScore = senderBestScore
x.senderMatchesPlayed = senderMatchesPlayed
x.senderMatchesWon = senderMatchesWon
x.senderWinPercentage = senderWinPercentage
//Receiver
x.receiverUserID = userID
x.receiverUserName = uActivity["userName"] as? String
x.receiverAverage = uActivity["averageScore"] as? Double
x.receiverBestScore = uActivity["bestScore"] as? Int
if (uActivity["played"] as! Double) < 1 || (uActivity["played"] as? Double) == nil {
x.receiverMatchesPlayed = 0
x.receiverMatchesWon = 0
x.receiverWinPercentage = 0
} else {
x.receiverMatchesPlayed = uActivity["played"] as? Double
x.receiverMatchesWon = uActivity["wins"] as? Double
x.receiverWinPercentage = ((uActivity["wins"] as! Double) / (uActivity["played"] as! Double) * 1000).rounded() / 10
}
if uActivity["playStyle"] as? String == nil {
x.receiverPlayStyle = "~No PlayStyle~"
} else {
x.receiverPlayStyle = uActivity["playStyle"] as! String
}
x.activity = activity
//append to array
validUserActivities.append(x)
}
}
}
completion(validUserActivities)
}
}
}
}
try this
static func getAllChallengesWithDistanceAllCode(activity:String, completion: #escaping ([Challenge]) -> Void) {
let db = Firestore.firestore()
let currUserID = Auth.auth().currentUser!.uid
var currUserName:String?
var distanceSetting:Int?
var senderAverage:Double?
var senderBestScore:Int?
var senderMatchesPlayed:Double?
var senderMatchesWon:Double?
var senderWinPercentage:Double?
var validUserActivities = [Challenge]()
db.collection("users").document(currUserID).getDocument { (snapshot, error) in
if error != nil || snapshot == nil {
return
}
currUserName = snapshot?.data()!["userName"] as? String
distanceSetting = snapshot?.data()!["distanceSetting"] as? Int
db.collection("userActivities").document(String(currUserID + activity)).getDocument { (snapshot, error) in
//check for error
//MARK: changed snapshot to shapshot!.data() below (possible debug tip)
if error != nil {
//is error or no data..??
return
}
if snapshot!.data() == nil {
return
}
//get profile from data proprty of snapshot
if let uActivity = snapshot!.data() {
senderBestScore = uActivity["bestScore"] as? Int
senderMatchesPlayed = uActivity["played"] as? Double
senderMatchesWon = uActivity["wins"] as? Double
senderAverage = uActivity["averageScore"] as? Double
senderWinPercentage = round((senderMatchesWon! / senderMatchesPlayed!) * 1000) / 10
if snapshot != nil && error == nil {
let uActivitiesData = snapshot!.documents
for uActivity in uActivitiesData {
let userID = uActivity["userID"] as! String
UserService.determineDistance(otherUserID: userID) { (determinedDistance) in
if determinedDistance! <= distanceSetting! && userID != currUserID {
var x = Challenge()
//Sender
x.senderUserID = currUserID
x.senderUserName = currUserName
x.senderAverage = senderAverage
x.senderBestScore = senderBestScore
x.senderMatchesPlayed = senderMatchesPlayed
x.senderMatchesWon = senderMatchesWon
x.senderWinPercentage = senderWinPercentage
//Receiver
x.receiverUserID = userID
x.receiverUserName = uActivity["userName"] as? String
x.receiverAverage = uActivity["averageScore"] as? Double
x.receiverBestScore = uActivity["bestScore"] as? Int
if (uActivity["played"] as! Double) < 1 || (uActivity["played"] as? Double) == nil {
x.receiverMatchesPlayed = 0
x.receiverMatchesWon = 0
x.receiverWinPercentage = 0
} else {
x.receiverMatchesPlayed = uActivity["played"] as? Double
x.receiverMatchesWon = uActivity["wins"] as? Double
x.receiverWinPercentage = ((uActivity["wins"] as! Double) / (uActivity["played"] as! Double) * 1000).rounded() / 10
}
if uActivity["playStyle"] as? String == nil {
x.receiverPlayStyle = "~No PlayStyle~"
} else {
x.receiverPlayStyle = uActivity["playStyle"] as! String
}
x.activity = activity
//append to array
validUserActivities.append(x)
}
}
}
completion(validUserActivities)
}
}
}
}
}
}
}
I solved this by doing the following:
Add a constant before the for-in loop counting the total number of query results
let documentCount = snapshot?.documents.count
Add a counter before the for-in loop starting at 0
var runCounter = 0
Increment the counter with each iteration at the beginning of the for-in loop
runCounter += 1
Add code to the end of the for-in loop to call the completion handler to return the results
if runCounter == documentCount {
completion(validChallenges)
}

How to get the row index of 2D Array?

I am new to Swift and I am using a 2D array for comparing and I need to get the row index once the condition is true but I got an error state that cannot invoke index with an argument list of type (of:Array<Float>)
My Code:
var entryCoordinate: [[Float]] = [[130.6,61.0],[167.5,61.0],[204.5,61.0],[243.6,61.0],[281.16,61.0],[315.3,61.0]]
for indexs in entryCoordinate
{
if indexs[0] == startPathPointX && indexs[1] == startPathPointY
{
let pathStartElement = indexs.index(of: indexs)
print(pathStartElement)
}
if indexs[0] == endPathPointX && indexs[1] == endPathPointY
{
let pathEndElement = indexs.index(of: indexs)
print(pathEndElement)
}
}
From your code with startPathPointY and endPathPointY you need to compare the second object from 2D array but you keep comparing the first one and you con use index(where:) with your array like this to get the pathStartElement and pathEndElement.
if let pathStartElement = entryCoordinate.index(where: { $0[0] == startPathPointX && $0[1] == startPathPointY }) {
print(pathStartElement)
}
if let pathEndElement = entryCoordinate.index(where: { $0[0] == endPathPointX && $0[1] == endPathPointY }) {
print(pathEndElement)
}
Try this code:
let myIndexPathStartElement = self.arrImagetData.index(where: { $0[0] == startPathPointX && $0[1] == startPathPointY })
let myIndexPathEndElement = self.arrImagetData.index(where: { $0[0] == endPathPointX && $0[1] == endPathPointY })

changing characters.string from nil to ""

var addressTxtFldArray = addressTxtFld.text!.characters.split{$0 == " "}.map(String.init)
if addressTxtFldArray.count == 1 {
addressTxtFldArray[1] = ""
addressTxtFldArray[2] = ""
addressTxtFldArray[3] = ""
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else if addressTxtFldArray.count == 2 {
addressTxtFldArray[2] = ""
addressTxtFldArray[3] = ""
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else if addressTxtFldArray.count == 3 {
addressTxtFldArray[3] = ""
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else if addressTxtFldArray.count == 4 {
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else {
addressTxtFldArray[5] = ""
}
var cityTxtFldArray = cityTxtFld.text!.characters.split{$0 == " "}.map(String.init)
if cityTxtFldArray.count == 1 {
cityTxtFldArray[1] = ""
}
var stateTxtFldArray = stateTxtFld.text!.characters.split{$0 == " "}.map(String.init)
if stateTxtFldArray.count == 1 {
stateTxtFldArray[1] = ""
}
var addressTxtFldDestArray = addressTxtFldDest.text!.characters.split{$0 == " "}.map(String.init)
if addressTxtFldDestArray.count == 1 {
addressTxtFldDestArray[1] = ""
addressTxtFldDestArray[2] = ""
addressTxtFldDestArray[3] = ""
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else if addressTxtFldDestArray.count == 2 {
addressTxtFldDestArray[2] = ""
addressTxtFldDestArray[3] = ""
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else if addressTxtFldDestArray.count == 3 {
addressTxtFldDestArray[3] = ""
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else if addressTxtFldDestArray.count == 4 {
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else {
addressTxtFldDestArray[5] = ""
}
var cityTxtFldDestArray = cityTxtFldDest.text!.characters.split{$0 == " "}.map(String.init)
if cityTxtFldDestArray.count == 1 {
cityTxtFldDestArray[1] = ""
}
var stateTxtFldDestArray = stateTxtFldDest.text!.characters.split{$0 == " "}.map(String.init)
if stateTxtFldDestArray.count == 1 {
stateTxtFldDestArray[1] = ""
}
Hello, so as you can see I am breaking down strings into individual words on the string, and then if they are empty, change them to "" instead of nil. However, it seems like this is still returning nil. Any suggestions would be greatly appreciated.
I don't see how you're not getting "Index out of range" errors with this code.
If you simply want to make sure your addressTxtFldArray variable always has exactly 6 entries, I would suggest something like this:
var addressTxtFldArray = (addressTxtFld.text!.characters
.split{$0 == " "}.map(String.init)
+ Array(count:6, repeatedValue:"")
)[0..<6]
If you really need the text field array to be field with "" instead of nil, I suggest you create a secondary array to save you from doing all the if comparisons and setting it to "".
var arrayContainer = [String](count: 10, repeatedValue: "")
let addressTxtFldArray = text.characters.split{$0 == " "}.map(String.init)
for (index,value) in addressTxtFldArray.enumerate()
{
arrayContainer[index] = value
}
print( arrayContainer)

How to show the current state you are located in when using reverseGeocodeLocation in swift

I'm testing out reverseGeocodeLocation with this app that shows your closest address. I've gotten everything to work except for the showing of the current state that you are in (IL, NY, ext.). How do I do that? This is my current code:
CLGeocoder().reverseGeocodeLocation(userLocation)
{ (placemarks, error) -> Void in
if error != nil
{
println(error)
}
else
{
let pm = CLPlacemark(placemark: placemarks![0] as CLPlacemark)
var subThoroughtare:String = ""
var thoroughfare:String = ""
var subLocality:String = ""
var subAdministrativeArea:String = ""
var postalCode:String = ""
var country:String = ""
if pm.subThoroughfare != nil {subThoroughtare = pm.subThoroughfare!}
if pm.thoroughfare != nil {thoroughfare = pm.thoroughfare!}
if pm.subLocality != nil {subLocality = pm.subLocality!}
if pm.subAdministrativeArea != nil {subAdministrativeArea = pm.subAdministrativeArea!}
if pm.postalCode != nil {postalCode = pm.postalCode!}
if pm.country != nil {country = pm.country!}
self.addressLabel.text = "\(subThoroughtare) \(thoroughfare) \n \(subLocality) \n \(postalCode) \n \(country)"
}
}
and the output is this (example location):
County Road 1760
79529
United States
for the state you want to look at the administrativeArea
let state = pm.administrativeArea;
If you look at the definition for the CLPlacemark class it shows..
var administrativeArea: String! { get } // state, eg. CA

Under what circumstances does reflectClass(o.runtimeType) return a different result from reflect(o).type?

from the dartdocs for InstanceMirror.type:
"Returns a mirror on the actual class of the reflectee. The class of the reflectee may differ from the object returned by invoking runtimeType on the reflectee."
so under what circumstances does reflectClass(o.runtimeType) return a different result from reflect(o).type?
I have tried with example code:
import 'dart:mirrors';
class A{}
void main() {
var string = "str";
var boolean = true;
var integer = 5;
var map = {};
var list = [];
var custom = new A();
var strRunT = string.runtimeType;
var strRefT = reflect(string).type.reflectedType;
var boolRunT = boolean.runtimeType;
var boolRefT = reflect(boolean).type.reflectedType;
var intRunT = integer.runtimeType;
var intRefT = reflect(integer).type.reflectedType;
var mapRunT = map.runtimeType;
var mapRefT = reflect(map).type.reflectedType;
var listRunT = list.runtimeType;
var listRefT = reflect(list).type.reflectedType;
var cusRunT = custom.runtimeType;
var cusRefT = reflect(custom).type.reflectedType;
print('string');
print('runtimeType = $strRunT');
print('reflectedType = $strRefT');
print('runT == refT = ${strRunT == strRefT}');
print('runT == String = ${strRunT == String}');
print('refT == String = ${strRefT == String}');
print('');
print('bool');
print('runtimeType = $boolRunT');
print('reflectedType = $boolRefT');
print('runT == refT = ${boolRunT == boolRefT}');
print('runT == bool = ${boolRunT == bool}');
print('refT == bool = ${boolRefT == bool}');
print('');
print('integer');
print('runtimeType = $intRunT');
print('reflectedType = $intRefT');
print('runT == refT = ${intRunT == intRefT}');
print('runT == int = ${intRunT == int}');
print('refT == int = ${intRefT == int}');
print('');
print('map');
print('runtimeType = $mapRunT');
print('reflectedType = $mapRefT');
print('runT == refT = ${mapRunT == mapRefT}');
print('runT == Map = ${mapRunT == Map}');
print('refT == Map = ${mapRefT == Map}');
print('');
print('list');
print('runtimeType = $listRunT');
print('reflectedType = $listRefT');
print('runT == refT = ${listRunT == listRefT}');
print('runT == List = ${listRunT == List}');
print('refT == List = ${listRefT == List}');
print('');
print('custom');
print('runtimeType = $cusRunT');
print('reflectedType = $cusRefT');
print('runT == refT = ${cusRunT == cusRefT}');
print('runT == A = ${cusRunT == A}');
print('refT == A = ${cusRefT == A}');
print('');
}
//OUTPUT
string
runtimeType = String
reflectedType = String
runT == refT = false
runT == String = true
refT == String = false
bool
runtimeType = bool
reflectedType = bool
runT == refT = true
runT == bool = true
refT == bool = true
integer
runtimeType = int
reflectedType = int
runT == refT = false
runT == int = true
refT == int = false
map
runtimeType = _LinkedHashMap
reflectedType = _LinkedHashMap
runT == refT = true
runT == Map = false
refT == Map = false
list
runtimeType = List
reflectedType = List
runT == refT = true
runT == List = false
refT == List = false
custom
runtimeType = A
reflectedType = A
runT == refT = true
runT == A = true
refT == A = true
additionally is there anyway of comparing 2 Types and finding if they are equal? as the example above shows that the 2 seperate Types of int aren't equal using the regular == operator.
You will get different results when a class overrides the runtimeType member. Basically an Object can lie on its type.
You can read more in the thread : example of wanting to override runtimeType?.
An example of what Alexandre said is the String type. In dart:core the String class overrides runtimeType to always return the base class type String. However in the VM there are a number of different runtime subtypes for String. i.e single character strings, ascii strings, utf8 strings. The mirror api returns the real underlying subtype.
See Gilad's (the API's designer) answer to this SO question.
"is there anyway of comparing 2 Types and finding if they are equal?"
There are three new methods coming soon that allow you to compare types when using mirrors: TypeMirror.isSubtypeOf, TypeMirror.isAssignableTo, ClassMirror.isSubclassOf.

Resources