Set a global variable from within GeoCoder function Swift - swift

I have a global variable "filterError" that is initially set to false before a switch statement. When the switch statement occurs, it will go through a dictionary, and for each key it will do a unique logic check on the value. If that value does not match certain criteria then the Boolean variable filterError will be set to true.
When the switch statement is complete, if filterErrror is false then the an action will occur like so:
//...switch statement...
if (filterErrror == false) {
//do something.....
}
The issue I am having is with the geocoder function which is a case in the switch statement. If the switch variable key = "area" then the below is executed:
var geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
guard let placemarks = placemarks,let location = placemarks.first?.location
else { print("Error in finding location") return }
let distanceInMeters = location.distance(from: coordinateSelf)
print("The distance between property and user in miles is: \(distanceInMeters/1609)")
distanceInMiles = distanceInMeters/1609
var radius = Double()
if searchRadius == "this area only" {
radius = 0.49999999999
} else {
radius = Double(Int(searchRadius)!)
}
if (radius < distanceInMiles) {
filterError = true
}
}
However, the filterError is still false after the switch statement has completed because the boolean value is not being changed. How do you set filterError to true from inside the geocoder?
This is the full code:
for filter in self.activeFilters {
switch filter.key {
case "listingType":
if(filter.value[0] != propertiesFirestore[i]["listingType"]![0]){
filterError = true
}
case "minBedsBound":
if(filter.value[0] != "No min. beds") {
if(filter.value[0].filter("01234567890.".contains) > propertiesFirestore[i]["bedroomCount"]![0]) {
filterError = true
}
}
case "maxBedsBound":
if(filter.value[0] != "No max. beds") {
if(Int(filter.value[0].filter("01234567890.".contains))! < Int(propertiesFirestore[i]["bedroomCount"]![0])!) {
filterError = true
}
}
case "minPriceBound":
if(filter.value[0] != "No min. price") {
if(Int(filter.value[0].filter("01234567890.".contains))! > Int(propertiesFirestore[i]["price"]![0])!) {
filterError = true
}
}
case "maxPriceBound":
if(filter.value[0] != "No max. price") {
if(Int(filter.value[0].filter("01234567890.".contains))! < Int(propertiesFirestore[i]["price"]![0])!) {
filterError = true
}
}
case "includeSharedOwnership":
if(filter.value[0] != propertiesFirestore[i]["sharedOwnership"]![0]) {
filterError = true
}
case "includeRetirementHomes":
if(filter.value[0] != propertiesFirestore[i]["retirementHome"]![0]) {
filterError = true
}
case "area":
print(userlatitude)
print(userlongitude)
let address = "\(propertiesFirestore[i]["area"]![0]), \(propertiesFirestore[i]["postcodePrefix"]![0])"
var propLat = String()
var propLong = String()
var distanceInMiles = Double()
var searchRadius = self.activeFilters["searchRadius"]![0]
let coordinateSelf = CLLocation(latitude: Double(userlatitude) as! CLLocationDegrees, longitude: Double(userlongitude) as! CLLocationDegrees)
var geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
guard
let placemarks = placemarks,
let location = placemarks.first?.location
else {
print("Error in finding location")
return
}
let distanceInMeters = location.distance(from: coordinateSelf)
print("The distance between property and user in miles is: \(distanceInMeters/1609)")
distanceInMiles = distanceInMeters/1609
var radius = Double()
if searchRadius == "this area only" {
radius = 0.49999999999
} else {
radius = Double(Int(searchRadius)!)
}
if (radius < distanceInMiles) {
filterError = true
}
}
case "keywords":
print("Filter keywords are: \(filter.value)")
for j in 0..<propertiesFirestore[i]["keywords"]!.count {
propertiesFirestore[i]["keywords"]![j] = propertiesFirestore[i]["keywords"]![j].lowercased()
}
for keyword in filter.value {
if propertiesFirestore[i]["keywords"] == nil {
filterError = true
} else if ((propertiesFirestore[i]["keywords"]!.contains(keyword.lowercased()))) {
print("found keyword")
} else {
filterError = true
}
}
default:
print("Unknown filter: \(filter.key)")
}
}
if filterError == false {
filterProperties.append(propertiesFirestore[i])
} else {
print("FITLER CATCHOUT")
}

Related

Add some calculation to CLLocationDistance

Here is my problem I can print in console double value (aka the distance) but I can't take a double and add the distance in a table view for exemple.
if previousLocation == nil {
previousLocation = locations.first
} else {
guard let latest = locations.first else { return }
let distanceInMeters = previousLocation?.distance(from: latest) ?? 0
print("Distance in meters: \(distanceInMeters)")
guard var unwrappedPaceNumber = paceNumber.first else { return }
let total = unwrappedPaceNumber += "\(distanceInMeters)"
paceNumber[0] = "\(total)"
tableView.reloadData()
previousLocation = latest
}
I finally ended up like that
If this can help
if previousLocation == nil {
previousLocation = locations.first
} else {
guard let latest = locations.first else { return }
let distanceInMeters = previousLocation?.distance(from: latest) ?? 0
var distanceRounded = distanceInMeters.rounded()
print("Distance in meters: \(distanceRounded)")
let unwrappedPaceNumber = paceNumber[0]
distanceRounded += Double(unwrappedPaceNumber)!
paceNumber[0] = "\(distanceRounded)"
print(paceNumber[0])
tableView.reloadData()
previousLocation = latest
}

My function just keeps looping, is it something to do with firestore?

My function is just looping at the print statement and not going into the ref db.collection Am I doing something wrong here? Thank you for any help. Im not really sure where to go, is this the best way to loop throw most of the data
func rat(){
var x = 0
while x != self.uniqueNumber{
let db = Firestore.firestore()
let indexString = String(x)
print(x)
let ref = db.collection("leaderboard").document(indexString)
ref.getDocument { (document,error) in
if error != nil{
print("cant get data")
}
if document != nil && document!.exists{
if let documentdata = document?.data() {
self.check = documentdata["points"] as! Int
self.uid = documentdata["uid"] as! String
x = x+1
print(x)
print("The user's ID was\(self.uid)")
if (self.check > self.firstPlace.placePoints){
self.secondPlace.placePoints = self.firstPlace.placePoints
self.secondPlace.placeNames = self.firstPlace.placeNames
self.firstPlace.placePoints = self.check
self.firstPlace.placeNames = self.uid
print("First Place was set to:\(self.firstPlace.placeNames)")
}else if(self.check < self.firstPlace.placePoints && self.secondPlace.placePoints < self.check){
self.thirdPlace.placePoints = self.secondPlace.placePoints
self.thirdPlace.placeNames = self.secondPlace.placeNames
self.secondPlace.placePoints = self.check
self.secondPlace.placeNames = self.uid
print("Second Place was set to:\(self.firstPlace.placeNames)")
}else if(self.check < self.secondPlace.placePoints && self.thirdPlace.placePoints < self.check){
self.thirdPlace.placePoints = self.check
self.thirdPlace.placeNames = self.uid
print("Third Place was set to:\(self.firstPlace.placeNames)")
}
}
if(x == self.uniqueNumber!-1){
print("This is the escape out")
self.setGuys()
}
}
}
}
}
Maybe you can try move the while x != self.uniqueNumber to inside the getDocument
func rat(){
var x = 0
let db = Firestore.firestore()
let indexString = String(x)
let ref = db.collection("leaderboard").document(indexString)
ref.getDocument { (document,error) in
if error != nil{
print("cant get data")
}
while x != self.uniqueNumber {
if document != nil && document!.exists{
if let documentdata = document?.data() {
x = x+1
}
if(x == self.uniqueNumber!-1){
self.setGuys()
}
}
}
}
}

I want to check the validation for both mobile number and email id in single textfield. How should I validate this?

I want to check the validation for both "Email id " and "mobile number" in single textfield. How should I validate the conditions for the same textfield?
Maybe this will help:
extension String {
var isPhoneNumber: Bool {
do {
let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
let matches = detector.matches(in: self, options: [], range: NSMakeRange(0, self.count))
if let res = matches.first {
return res.resultType == .phoneNumber && res.range.location == 0 && res.range.length == self.count
} else {
return false
}
} catch {
return false
}
}
}
extension String {
var isInt: Bool {
return Int(self) != nil
}
}
func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluate(with: testStr)
}
if textField.text.characterCount > 6 {
if textField.text.isInt == true {
print("this might be users phone number"
} else if isValidEmail(testStr:textField.text) {
print("this might be users mail")
} else {
print("user entered wrong value or nothing")
}

Sorting mixed String-Int Strings numerically as the primary order, then alphabetically in swift

For a String which have both String and Int values (one of each) is it possible to do simple sort that will give the items ordered in numerical order as the primary order and alphabetical as the secondary order
var nameArray = ["Dave7", "Bob8", "Cathy9", "Henry10", "Susan10", "Pat11", "Steve12", "Dan12", "Ken1", "Sean2", "Howard3", "Dixie3", "Newman5", "Billy6"]
var sortedNameArray = nameArray.sort { $0.compare($1, options: .NumericSearch) == .OrderedAscending }
print(sortedNameArray) // gives the following:
Don't want this -> ["Billy6", "Bob8", "Cathy9", "Dan12", "Dave7", "Dixie3", "Henry10", "Howard3", "Ken1", "Newman5", "Pat11", "Sean2", "Steve12", "Susan10"]
Even though .NumericSearch was used the result is alphabetical.
I was able to get the desired result using a custom binary tree. Which gives the results:
Ken1 Sean2 Dixie3 Howard3 Newman5 Billy6 Dave7 Bob8 Cathy9 Henry10 Susan10 Pat11 Dan12 Steve12
But is there a simpler solution?
extension String {
var integerValue: Int? {
return Int(self)
}
}
func extractValueFromString(theString:String)->Int{
var catNumber: [Character] = []
//print("theString \(theString)")
for character in theString.characters{
var characterString = String(character)
if var value = characterString.integerValue { //if we don't check program crashes
//if numberSet.contains(Int(String(character))!) { //another way to check but redundant here
catNumber.append(character)
//print(catNumber)
// }
}
}
let numberString = String(catNumber)
return Int(numberString)!
}
class Node{
//nodes now only arrange strings
var data = ""
var value = Int()
var left:Node?;
var right:Node?;
deinit {
//print("deleting \(data)")
// print("node deleted")
}
init(data:String){
self.data = data;
//print(data)
}
}
class binaryTreeSort{
var root:Node?
init(){
}
deinit {
//print("tree deleted")
}
func getRoot()->Node{
return root!
}
func insertNewValue(data:String){
let newNode = Node(data:data)
var node:Node? = root
if (node == nil){
root = newNode
}
while (node != nil) {
let currentValue = node?.data
if currentValue == ""{
node?.data = data
return
}
if currentValue == data {
//we don't want duplicates.
return
}
if extractValueFromString(currentValue!) < extractValueFromString(data) {
if (node!.right != nil) {
node = node!.right
//print("Going Right at data \(node!.data)")
}else{
node!.right = newNode
//print("Going New Right at data \(node!.data)")
return
}
}else if extractValueFromString(currentValue!) == extractValueFromString(data){
if currentValue < data {
if (node!.right != nil) {
node = node!.right
//print("Going Right at data \(node!.data)")
}else{
node!.right = newNode
//print("Going New Right at data \(node!.data)")
return
}
}else{
if (node!.left != nil) {
//print("Going Left at data \(node!.data)")
node = node!.left
}else{
node!.left = newNode
//print("Going New Left at data \(node!.data)")
return
}
}
}
else{
if (node!.left != nil) {
//print("Going Left at data \(node!.data)")
node = node!.left
}else{
node!.left = newNode
//print("Going New Left at data \(node!.data)")
return
}
}
}
}
func inorderPrint(baseNode:Node){
if(baseNode.left != nil)
{
inorderPrint(baseNode.left!);
//print(" \(baseNode.data)")
}
print("\(baseNode.data)")
if(baseNode.right != nil)
{
inorderPrint(baseNode.right!)
//print(" \(baseNode.data)")
}
}
func reverseOrderPrint(baseNode:Node){
if(baseNode.right != nil)
{
reverseOrderPrint(baseNode.right!)
//print(" \(baseNode.data)")
}
print("\(baseNode.data)")
if(baseNode.left != nil)
{
reverseOrderPrint(baseNode.left!);
//print(" \(baseNode.data)")
}
}
}
var myBinaryTreeSort:binaryTreeSort? = binaryTreeSort()
for item in nameArray{
//print(item)
myBinaryTreeSort!.insertNewValue(item)
}
myBinaryTreeSort!.inorderPrint(myBinaryTreeSort!.getRoot())
print("---------------")
myBinaryTreeSort!.reverseOrderPrint(myBinaryTreeSort!.getRoot())
myBinaryTreeSort = nil //delete the tree
Use map to split the names into parts, sort to sort by number and name, and then map to restore the original:
func splitName(name:String) -> (String, Int) {
if let range = name.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()) {
return (name[name.startIndex..<range.startIndex], Int(name[range.startIndex..<name.endIndex])!)
} else {
return (name, 0)
}
}
print(nameArray.map(splitName).sort({ lhs, rhs in
if lhs.1 < rhs.1 {
return true
} else if lhs.1 > rhs.1 {
return false
} else {
return lhs.0 < rhs.0
}
}).map({ "\($0.0)\($0.1)" }))
Some other ways it could be done would be to maintain element 0 of the tuple as the full name (with numbers) and then the final map just becomes map({ $0.0 }) Depending on sizes, this may be more optimal than splitting the name each time it's compared.
If you have an array, you can sort with a custom closure.
For example:
nameArray.sort({extractValueFromString($0) < extractValueFromString($1)})
Will get you close. You just need to check if they are equal and return $0 < $1 instead.
Here's how I solved this, doing something similar to what #Lou-Franco alluded to:
func endInteger(word: String) -> Int {
if let range = word.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()){
let numberSubstring = word.substringFromIndex(range.startIndex)
return Int(numberSubstring) ?? 0
}
return 0
}
let sortedArray = yourArray.sort{endInteger($1) > endInteger($0)}

Swift: UIRefreshControl does not pull through when dragging down

I have a working UITableView in which I added a UIRefreshControl like this:
var refresher: UIRefreshControl!
...
// this is ViewDidLoad()
// pull to refresh
refresher = UIRefreshControl()
refresher.tintColor = globalClass.blue
refresher.attributedTitle = NSAttributedString(string: "")
refresher.addTarget(self, action: "loadFriends", forControlEvents: UIControlEvents.ValueChanged)
friendTableView.addSubview(refresher)
This works well on other UITableViews, but not on this one for some reason. The spinner never really spins and just snaps to the top when the dragging stops. What could cause this?
EDIT: loadFriends function
//load friends
func loadFriends() {
globalClass.requestsIn = []
globalClass.requestsOut = []
globalClass.finalSections = []
globalClass.myFriends = []
finalSections = []
sectionsG1 = []
let queryIn1 = PFQuery(className:"Friendship")
queryIn1.whereKey("toUser", equalTo: PFUser.currentUser()!.username!)
let queryOut = PFQuery(className:"Friendship")
queryOut.whereKey("fromUser", equalTo: PFUser.currentUser()!.username!)
let query = PFQuery.orQueryWithSubqueries([queryIn1, queryOut])
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if objects!.count == 0 {
self.friendtTableView.reloadData()
self.text()
} else {
for object in objects! {
let toUser:String = object["toUser"] as! String
let status:String = object["status"] as! String
if toUser == PFUser.currentUser()?.username {
if status == "pending" {
globalClass.requestsIn.append(object["fromUser"] as! String)
self.update()
} else if status == "approved" {
globalClass.myFriends.append(object["fromUser"] as! String)
globalClass.myFriends = globalClass.myFriends.sorted { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
self.update()
}
} else { if status == "pending" || status == "rejected" {
globalClass.requestsOut.append(object["toUser"] as! String)
self.update()
} else if status == "approved" {
globalClass.myFriends.append(object["toUser"] as! String)
globalClass.myFriends = globalClass.myFriends.sorted { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
self.update()
}
}
}
}
if self.tableSegment == 1 {
if globalClass.requestsIn.count == 0 {
self.friendTableView.reloadData()
self.text()
} else {
}
} else if self.tableSegment == 2 {
if globalClass.requestsOut.count == 0 {
self.friendTableView.reloadData()
self.text()
} else {
}
} else if self.tableSegment == 0 {
if globalClass.myFriends.count == 0 {
self.friendTableView.reloadData()
self.text()
} else {
}
}
self.refresher.endRefreshing()
} else {
}
}
}