iOS Simulator and reverseGeocodeLocation - ios

Is it normal for the iOS simulator to not work every so often with regards to grabbing the location? My project for this app keeps crashing 50% of the time whenever I run the simulator...but I can't seem to pinpoint the problem within the code itself. If the problem is indeed in the code itself, can anyone please help me find the problem? The error is "fatal error: unexpectedly found nil while unwrapping an Optional value" and it says it occurs in my refreshPost function on the line
eventsPostedQuery.whereKey("CityName", equalTo: self.usersLocation)
I am using Parse as part of this app. Also, I have a viewDidAppear to refresh the "Posts", is this a correct way to go about this? Greatly appreciated!
import UIKit
import Parse
class HomeTableViewController: UITableViewController, CLLocationManagerDelegate {
#IBOutlet weak var navigationBar: UINavigationItem!
#IBOutlet weak var menuButton: UIBarButtonItem!
#IBAction func cancelPost(segue: UIStoryboardSegue) {
}
var users = [String: String]()
var usernames = [String]()
var eventInfo = [String]()
var imageFiles = [PFFile]()
var usersLocation: String!
var locationManager: CLLocationManager!
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation: CLLocation = locations[0]
CLGeocoder().reverseGeocodeLocation(userLocation) { (placemarks, error) -> Void in
if error != nil {
print(error)
} else {
let p = placemarks?.first // ".first" returns the first element in the collection, or nil if its empty
// this code above will equal the first element in the placemarks array
let city = p?.locality != nil ? p?.locality : ""
let state = p?.administrativeArea != nil ? p?.administrativeArea : ""
self.navigationBar.title = ("\(city!), \(state!)")
self.usersLocation = ("\(city!), \(state!)")
self.locationManager.stopUpdatingLocation()
print(self.usersLocation)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
menuButton.target = self.revealViewController()
menuButton.action = Selector("revealToggle:")
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 250.0
}
override func viewDidAppear(animated: Bool) {
refreshPosts()
}
func refreshPosts() {
let query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.users.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
self.eventInfo.removeAll(keepCapacity: true)
self.imageFiles.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
self.users[user.objectId!] = user.username!
}
}
}
let eventsPostedQuery = PFQuery(className: "PostEvent")
eventsPostedQuery.whereKey("CityName", equalTo: self.usersLocation)
eventsPostedQuery.orderByDescending("createdAt")
eventsPostedQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let events = objects {
for event in events {
self.imageFiles.append(event["imageFile"] as! PFFile)
self.eventInfo.append(event["eventInfo"] as! String)
self.usernames.append(self.users[event["userId"] as! String]!)
self.tableView.reloadData()
}
}
})
})
}

You should call
refreshPosts()
from inside the else block of this completion block:
CLGeocoder().reverseGeocodeLocation(userLocation) { (placemarks, error) -> Void in
if error != nil {
print(error)
} else {
let p = placemarks?.first // ".first" returns the first element in the collection, or nil if its empty
// this code above will equal the first element in the placemarks array
let city = p?.locality != nil ? p?.locality : ""
let state = p?.administrativeArea != nil ? p?.administrativeArea : ""
self.navigationBar.title = ("\(city!), \(state!)")
self.usersLocation = ("\(city!), \(state!)")
self.locationManager.stopUpdatingLocation()
print(self.usersLocation)
}
}
As in only update the post if the reverse geocoder is finished and didn't return an error.

Related

I get this error when i run my app. Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

Whenever I run my app, it always crashes anywhere it states currentUserID. Not sure why.
I printed the the currentUserID value and its nil.
How can I correct it so it runs my app well. I can share the rest of the code if needed.
import UIKit
import MapKit
import CoreLocation
import Firebase
//import FirebaseDatabase
enum AnnotationType {
case pickup
case destination
case driver
}
enum ButtonAction {
case requestRide
case getDirectionsToPassenger
case getDirectionToDestination
case startTrip
case endTrip
}
class HomeVC: UIViewController, Alertable {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var centerMapBtn: UIButton!
#IBOutlet weak var destinationTextField: UITextField!
#IBOutlet weak var destinationCircle: UIView!
#IBOutlet weak var cancelBtn: UIButton!
#IBOutlet weak var actionBtn: UIButton!
var delegate: CenterVCDelegate?
var manager: CLLocationManager?
let currentUserId = Auth.auth().currentUser?.uid
// "IRD70YtgEyWRpaH8LkkjHZmjXPo1"
var ref: DatabaseReference!
var regionRadius: CLLocationDistance = 1000
var tableView = UITableView()
var matchingItems: [MKMapItem] = [MKMapItem]()
var route: MKRoute!
var selectedItemPlacemark: MKPlacemark? = nil
var actionForButton: ButtonAction = .requestRide
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
// print(ref.child("users").value(forKey: "users"))
self.ref.child("userse").childByAutoId().setValue("wise")
self.ref.child("users").child("sdsd").setValue("data")
// print(Auth.auth().currentUser?.uid)
// print(currentUserId)
manager = CLLocationManager()
manager?.delegate = self
manager?.desiredAccuracy = kCLLocationAccuracyBest
checkLocationAuthStatus()
mapView.delegate = self
destinationTextField.delegate = self
centerMapOnUserLocation()
DataService.instance.REF_DRIVERS.observe(.value, with: { (snapshot) in
self.loadDriverAnnotationFromFB()
DataService.instance.passengerIsOnTrip(passengerKey: self.currentUserId!, handler: { (isOnTrip, driverKey, tripKey) in
if isOnTrip == true {
self.zoom(toFitAnnotationsFromMapView: self.mapView, forActiveTripWithDriver: true, withKey: driverKey)
}
})
})
cancelBtn.alpha = 0.0
UpdateService.instance.observeTrips { (tripDict) in
if let tripDict = tripDict {
let pickupCoordinateArray = tripDict["pickupCoordinate"] as! NSArray
let tripKey = tripDict["passengerKey"] as! String
let acceptanceStatus = tripDict["tripIsAccepted"] as! Bool
if acceptanceStatus == false {
//Broadcast to all driver
DataService.instance.driverIsAvailable(key: self.currentUserId!, handler: { (available) in
//check for errors
if let available = available {
if available == true {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let pickupVC = storyboard.instantiateViewController(withIdentifier: "PickupVC") as? PickupVC
pickupVC?.initData(coordinate: CLLocationCoordinate2D(latitude: pickupCoordinateArray[0] as! CLLocationDegrees, longitude: pickupCoordinateArray[1] as! CLLocationDegrees), passengerKey: tripKey)
self.present(pickupVC!, animated: true, completion: nil)
}
}
})
}
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if self.currentUserId == nil {
print("login")
}
DataService.instance.userIsDriver(userKey: self.currentUserId!, handler: { (status) in
if status == true {
self.buttonsForDriver(areHidden: true)
}
})
DataService.instance.REF_TRIPS.observe(.childRemoved, with: { (removedTripSnapshot) in
let removedTripDict = removedTripSnapshot.value as? [String: AnyObject]
if removedTripDict?["driverKey"] != nil {
DataService.instance.REF_DRIVERS.child(removedTripDict?["driverKey"] as! String).updateChildValues(["driverIsOnTrip": false])
}
DataService.instance.userIsDriver(userKey: self.currentUserId!, handler: { (isDriver) in
if isDriver == true {
// Remove Overlays and annotation and hide request ride and cancel button
self.removeOverlaysAndAnnotations(forDrivers: false, forPassengers: true)
} else {
self.cancelBtn.fadeTo(alphaValue: 0.0, withDuration: 0.2)
self.destinationTextField.isUserInteractionEnabled = true
self.destinationTextField.text = ""
// Remove all map annotation and overlays
self.removeOverlaysAndAnnotations(forDrivers: false, forPassengers: true)
self.centerMapOnUserLocation()
}
})
})
DataService.instance.driverIsOnTrip(driverkey: self.currentUserId!, handler: { (isOnTrip, driverKey, tripKey) in
if isOnTrip == true {
DataService.instance.REF_TRIPS.observeSingleEvent(of: .value, with: { (tripSnapshot) in
if let tripSnapshot = tripSnapshot.children.allObjects as? [DataSnapshot] {
for trip in tripSnapshot {
if trip.childSnapshot(forPath: "driverKey").value as? String == self.currentUserId! {
let pickupCoordinateArray = trip.childSnapshot(forPath: "pickupCoordinate").value as! NSArray
let pickupCoordinate = CLLocationCoordinate2D(latitude: pickupCoordinateArray[0] as! CLLocationDegrees, longitude: pickupCoordinateArray[1] as! CLLocationDegrees)
let pickupPlacemark = MKPlacemark(coordinate: pickupCoordinate)
self.dropPinFor(placemark: pickupPlacemark)
self.searchMapKitForResultsWithPolyline(forOriginMapItem: nil, withDestinationMapItem: MKMapItem(placemark: pickupPlacemark))
self.setCustomRegion(forAnnotationType: .pickup, withCoordinate: pickupCoordinate)
self.actionForButton = .getDirectionsToPassenger
self.actionBtn.setTitle("GET DIRECTION", for: .normal)
// Fade in the action button
self.buttonsForDriver(areHidden: false)
}
}
}
})
There are a few issues that should be addressed and then a core issue.
The first thing is that Auth.auth().currentUser? is an optional - meaning that it could have a value or could be nil. Doing this..
let currentUserId = Auth.auth().currentUser?.uid
is telling your code that no matter if its got a value or nil, attempt to assign the .uid to currentUserId.
Protect your code by safely unwrapping options
guard let currentUser = Auth.auth().currentUser else {return}
//now you can access currentUser as it won't be nil
or
if let currentUser = Auth.auth().currentUser {
print("user is authenticated and currentUser is not nil")
} else {
print("not authenticated")
}
Now the core of the issue is, as far as I can see, you're not authenticating the user at all and that needs to happen prior to accessing Auth.auth().currentUser
Here's a complete authentication function with error handling
func authUser(user: String, pw: String) {
Auth.auth().signIn(withEmail: user, password: pw, completion: { (auth, error) in
if let x = error {
let err = x as NSError
switch err.code {
case AuthErrorCode.wrongPassword.rawValue:
print("wrong password")
case AuthErrorCode.invalidEmail.rawValue:
print("invalued email")
default:
print("unknown error")
}
} else {
if let user = auth?.user { //note; safely unwrap optional
print("uid: \(user.uid)")
}
}
})
}

Indexpath.row repeat lead to intermittent Index out of range error

When tableview is first loaded, the index print(indexPath.row) shows index 0,1,2. When the tableview is loaded again the indexpath repeats itself 3 times, in the debugger it will be 0,1,2,0,1,2,0,1,2. This happens within two seconds, but if you scroll the tableview before this there is a fatal error: Index out of range error.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! EstablishmentCell
let object = Model.sharedInstance.items[indexPath.row]
cell.venueDistance.text = object.venueDistance
cell.titleLabel.text = object.name
object.loadCoverPhoto { image in
dispatch_async(dispatch_get_main_queue()) {
cell.coverPhotoView.image = image
}
}
let myCustomSelectionColorView = UIView()
myCustomSelectionColorView.backgroundColor = UIColor(red:0.16, green:0.65, blue:0.64, alpha:1.0)
cell.selectedBackgroundView = myCustomSelectionColorView
}
}self.activityIndicatorView.stopAnimating()
return cell
}}
EDIT1:
Establishment Class
class Establishment: NSObject {
//Properties
var record: CKRecord!
var name: String!
var establishmentDescription: String!
var establishmentOpening: String!
var venueLocation: CLLocation!
weak var database: CKDatabase!
var assetCount = 0
var establishmentDistance: String!
let locationManager = CLLocationManager()
//Map Annotation Properties
// var coordinate: CLLocationCoordinate2D {
// return venueLocation.coordinate
// }
var title: String? {
return name
}
var venueDescription: String? {
return establishmentDescription
}
var venueDistance: String? {
return establishmentDistance
}
//Initializers
init(record: CKRecord, database: CKDatabase) {
self.record = record
self.database = database
//let venueLocation = record["Location"] as? CLLocation
//let location = CLLocation()
//let userLocation = CLLocation(latitude: 51.211963, longitude: -0.769298)
self.name = record["Name"] as? String
self.establishmentDescription = record["Description"] as? String
self.establishmentOpening = record["OpeningTimes"] as? String
self.venueLocation = record["Location"] as? CLLocation
let location = locationManager.location
let distanceBetween: CLLocationDistance = (venueLocation!.distanceFromLocation(location!))
self.establishmentDistance = String(format: "%.f", distanceBetween)
}
func fetchPhotos(completion: (assets: [CKRecord]!) ->()) {
let predicate = NSPredicate(format: "Establishment == %#", record)
let query = CKQuery(recordType: "EstablishmentPhoto", predicate: predicate)
// Intermediate Extension Point - with cursors
database.performQuery(query, inZoneWithID: nil) { [weak self] results, error in
defer {
completion(assets: results)
}
guard error == nil,
let results = results else {
return
}
self?.assetCount = results.count
}
}
func loadCoverPhoto(completion:(photo: UIImage!) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
var image: UIImage!
defer {
completion(photo: image)
}
guard let asset = self.record["CoverPhoto"] as? CKAsset,
path = asset.fileURL.path,
imageData = NSData(contentsOfFile: path) else {
return
}
image = UIImage(data: imageData)
}
}
Model Class:
protocol ModelDelegate {
func errorUpdating(error:NSError)
func modelUpdated() class Model{
//Properties
let EstablishmentType = "Establishment"
static let sharedInstance = Model()
var delegate: ModelDelegate?
var items: [Establishment] = []
let userInfo: UserInfo
let locationManager = CLLocationManager()
var latitude : String!
var longitude : String!
var isLoading = Bool()
//Define Databases
// Represents the default container specified in the iCloud section of the Capabilities tab for the project.
let container: CKContainer
let publicDB: CKDatabase
let privateDB: CKDatabase
//Indicator
// Ask for Authorisation from the User.
func requestLocation() {
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locationManager.distanceFilter = 10
self.locationManager.startUpdatingLocation()
// Check if this app has permission to use location services
let authorizationStatus:CLAuthorizationStatus = CLLocationManager.authorizationStatus()
if authorizationStatus == CLAuthorizationStatus.Denied {
// TODO: Tell user that app functionality may be limited
}
else if authorizationStatus == CLAuthorizationStatus.NotDetermined {
// Manually prompt the user for permission
self.locationManager.requestWhenInUseAuthorization()
}
else if authorizationStatus == CLAuthorizationStatus.AuthorizedWhenInUse {
self.locationManager.startUpdatingLocation()
}
}
//Initializers
init () {
container = CKContainer.defaultContainer()
publicDB = container.publicCloudDatabase
privateDB = container.privateCloudDatabase
userInfo = UserInfo(container: container)
}
#objc func refresh() {
let location = locationManager.location
let radius = CGFloat(1000)
let predicate = NSPredicate(format: "distanceToLocation:fromLocation:(%K,%#) < %f", "Location", location!, radius)
let query = CKQuery(recordType: "Establishment", predicate: predicate)
let sort = CKLocationSortDescriptor(key: "Location", relativeLocation: location!)
query.sortDescriptors = [sort]
publicDB.performQuery(query, inZoneWithID: nil) { [unowned self] results, error in
guard error == nil else {
dispatch_async(dispatch_get_main_queue()) {
self.delegate?.errorUpdating(error!)
print("Cloud Query Error - Refresh: \(error)")
}
return
}
self.items.removeAll(keepCapacity: true)
for record in results! {
let establishment = Establishment(record: record, database: self.publicDB)
self.items.append(establishment)
}
dispatch_async(dispatch_get_main_queue()) {
self.delegate?.modelUpdated()
}
}
}
func establishment(ref: CKReference) -> Establishment! {
let matching = items.filter { $0.record.recordID == ref.recordID }
return matching.first
}}
Mention all datasource method here which are added in your code .
And also check your following method :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return Model.sharedInstance.items.count
}

Attempting to run a function when Google Maps Marker is tapped

I am attempting to run a function that will play a video when a marker on google maps is tapped however I cannot get that function to run although there are no errors. Perhaps there is an issue with my logic or control flow. Below is my view controller as well as the function.
#IBOutlet weak var viewMap: GMSMapView!
var placesClient: GMSPlacesClient?
var url : NSURL?
var videoData : NSData?
var doUpload : Bool?
var FriendsOrPublic : String?
var dataPath : String?
var gmsPlace : GMSPlace?
var gpsCoordinates : CLLocationCoordinate2D?
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
//placesClient = GMSPlacesClient()
var gmsPlace : GMSPlace?
let placesClient = GMSPlacesClient.sharedClient()
placesClient.currentPlaceWithCallback { (placeLikelihoods, error) -> Void in
guard error == nil else {
print("Current Place error: \(error!.localizedDescription)")
return
}
if let placeLikelihoods = placeLikelihoods {
for likelihood in placeLikelihoods.likelihoods {
gmsPlace = likelihood.place
//print("Current Place name \(gmsPlace.name) at likelihood \(likelihood.likelihood)")
//print("Current Place address \(gmsPlace.formattedAddress)")
//print("Current Place attributions \(gmsPlace.attributions)")
//print("Current PlaceID \(gmsPlace.placeID)")
self.gpsCoordinates = (gmsPlace!.coordinate)
}
//print(self.gpsCoordinates)
}
}
let testObject = PFObject(className: "TestObject")
testObject["foo"] = "bar"
testObject.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
print("Object has been saved.")
}
print(url)
print(videoData)
print(doUpload)
print(FriendsOrPublic)
print(dataPath)
if doUpload == true {
Upload()
}
Download()
viewMap.delegate = self
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
//print("locations = \(locValue.latitude) \(locValue.longitude)")
gpsCoordinates = locValue
let camera = GMSCameraPosition.cameraWithTarget(gpsCoordinates!, zoom: 16.9)
//let camera = GMSCamera
print(camera)
viewMap.camera = camera
viewMap.myLocationEnabled = true
viewMap.settings.myLocationButton = false
let marker = GMSMarker()
marker.position = self.gpsCoordinates!
marker.title = "Newport Beach"
marker.snippet = "California"
marker.map = viewMap
locationManager.stopUpdatingLocation()
}
var marker : GMSMarker!
func Download() {
let query = PFQuery(className:"UploadedVideoCurrent")
// query.whereKey("GPS", equalTo: "ChIJTbSOh8Pf3IARt311y2Wqspc")
query.whereKey("typeofPost", equalTo: "Public")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) coordinates.")
// Do something with the found objects
if let objects = objects {
for object in objects {
print(object.objectForKey("GPS"))
let postsLat = object.objectForKey("GPS")!.latitude as Double
let postsLong = object.objectForKey("GPS")!.longitude as Double
let position: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: postsLat, longitude:postsLong)
self.marker = GMSMarker(position: position)
self.marker.map = self.viewMap
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
}
func viewMap(viewMap: GMSMapView, didTapMarker marker: GMSMarker)
{
print("tapped")
}
You're calling the wrong delegate function. you should still call the function "mapView" because that's how the delegate function is defined, even though your map itself is declared as "viewMap"
func mapView(mapView: GMSMapView!, didTapMarker marker: GMSMarker!) -> Bool {
print("tapped")
}

iOS swift parse update multiple objects

i have 2 objects(parent , child) with cash and value fields for each object .
at pressing a button , it does some calculations and update objects fields to the new values ,I'm able to update the parent fields to the new values but the child values remain as they are.
heres the full code :
#IBOutlet weak var childImage: UIImageView!
#IBOutlet weak var childInfo: UILabel!
#IBOutlet weak var adoptButton: UIButton!
#IBOutlet weak var nextButton: UIButton!
#IBOutlet weak var malesButton: UIButton!
#IBOutlet weak var femalesButton: UIButton!
#IBOutlet weak var statusLabel: UILabel!
// empty array to load ids from parse
var objectIds = [String]()
// counter is the index number of Ids array
var counter = 0
var childCash = 0
var childValue = 0
var childId: String? = ""
var childName = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
loadingMalesIds()
childInfo.hidden = true
adoptButton.hidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func maleButtonPressed(sender: AnyObject) {
loadingMalesIds()
}
#IBAction func femaleButtonPressed(sender: AnyObject) {
loadingFemalesIds()
}
#IBAction func nextButtonPressed(sender: AnyObject) {
counter++
if (counter <= objectIds.count){
var query = PFQuery(className:"_User")
query.getObjectInBackgroundWithId(objectIds[(counter - 1) ] ) {
(child: PFObject?, error: NSError?) -> Void in
if error == nil && child != nil {
self.childName = child?["username"] as! String
self.childValue = child?["value"] as! Int
var status = child?["status"] as! String
self.childCash = child?["cash"] as! Int
self.childId = (child?.objectId)!
let userImageFile = child?["userImage"] as! PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
self.childImage.layer.borderWidth = 2
self.childImage.layer.masksToBounds = true
self.childImage.layer.borderColor = UIColor.whiteColor().CGColor
self.childImage.image = image
}
}
}
self.statusLabel.text = status
self.childInfo.text = "\(self.childName), $\(self.childValue)"
} else {
println(error)
} // end of if error == nil
}
}else{
counter = 0
} //end of if (counter <= objectIds.count)
childInfo.hidden = false
adoptButton.hidden = false
}//end of method
func loadingMalesIds(){
objectIds.removeAll(keepCapacity: false)
var query = PFQuery(className:"_User")
// get Ids with a condition that users are males
query.whereKey("gender", equalTo:"male")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
if let objects = objects as? [PFObject] {
for object in objects {
self.objectIds.append((object.objectId)! as String)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
self.malesButton.enabled = false
self.femalesButton.enabled = true
}
func loadingFemalesIds(){
objectIds.removeAll(keepCapacity: false)
var query = PFQuery(className:"_User")
// get Ids with a condition that users are males
query.whereKey("gender", equalTo:"female")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
if let objects = objects as? [PFObject] {
for object in objects {
self.objectIds.append((object.objectId)! as String)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
self.malesButton.enabled = true
self.femalesButton.enabled = false
}
#IBAction func adoptPressed(sender: AnyObject) {
// get parent cash and value
let cash = PFUser.currentUser()!["cash"] as? Int
let value = PFUser.currentUser()!["value"] as? Int
let numberOfChildren = PFUser.currentUser()!["numberOfChildren"] as? Int
//check
if (cash < childValue){
noCashAlert()
}else{
var parentNewCash = cash! - childValue
var parentNewValue = value! + childValue
var childNewCash = childCash + (10 * childValue / 100)
//number of children
var newNumberOfChildren = numberOfChildren! + 1
// save parent new cash and value
var queryParent = PFQuery(className:"_User")
//get parent ID
var currentUserId = PFUser.currentUser()?.objectId!
println("current: \(currentUserId)")
// do the saving operation
queryParent.getObjectInBackgroundWithId(currentUserId!) {
(parent: PFObject?, error: NSError?) -> Void in
if error != nil {
println(error)
} else if let parent = parent {
//parent new cash
parent["cash"] = parentNewCash
//parent new value
parent["value"] = parentNewValue
//parent number of children
parent["numberOfChildren"] = newNumberOfChildren
parent.saveInBackground()
}
}//end parent query
var queryChild = PFQuery(className:"_User")
queryChild.getObjectInBackgroundWithId(self.childId!) {
(child: PFObject?, error: NSError?) -> Void in
if error != nil {
println(error)
} else if let child = child {
child["cash"] = childNewCash
child.saveInBackground()
}
}//end child query
}
}
func noCashAlert(){
let message = "Sorry!, You Don't Have Enough Money,You Can Use Money Printer For Some Extra Cash "
let okText = "Ok"
let alert = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okayButton = UIAlertAction(title: okText, style: UIAlertActionStyle.Cancel, handler: nil)
alert.addAction(okayButton)
self.presentViewController(alert, animated: true, completion: nil)
}
}
We need more information.
One possibility is that childValue is declared as an Int, and its value is less than 100, so that childValue / 100 is 0. Remember integer division vs. floating-point division. You could say instead Double(childValue) / 100.0 to force floating point.
Have you used a debugger or debugging println()s to determine if childNewCash is what you expect?
Another possibility is that child is declared as a struct not a class, but this is very unlikely given the context.
As a minor style point, you probably want:
if let e = error {
println(e)
}
so that you don't get Optional(...) in your output.
This answer should have gone into comments section but for now I'll keep it and just edit...This is impossible to answer without a lot more context. When you say "it's not updating at all" where and when are you looking?
If you're looking in the getObjectInBackgroundWithId completion handler right after setting the cash value, I'm sure you'd get the right value back.
Are you looking in the cloud database? With a background save there's some delay, and you could be looking too early. If there's conflicting saves, the save tasks could be overwriting one another. How about using the optional completion handler for saveInBackground() to make sure you're not checking too soon?

Swift Local Search MapView

I'm currently integrating local search into my iOS app, and I'm running into some problems. Everything is building fine with no errors, but the search function is just not happening. I've ran it on the simulator and on my iOS Device, and the function doesn't seem to be running. I've checked my console log and nothing is going through.
italic*Edit: I've fixed the problem with the method not being called, but I'm now getting the following error. I can paste the whole call stack if needed
"searchText:]: unrecognized selector sent to instance 0x7ff2f1c1c3b0
2015-02-16 21:10:26.818 THINKStatus[60477:1795955] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[THINKStatus.loggedinViewController searchText:]: unrecognized selector sent to instance 0x7ff2f1c1c3b0'"
Here is the code for my view controller:
import Foundation
import UIKit
import MapKit
class loggedinViewController : UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var searchText: UITextField!
var matchingItems: [MKMapItem] = [MKMapItem]()
let service = "tgsLogin"
let userAccount = "tgsLoginUser"
let key = "RandomKey"
#IBAction func loggedinActionButton(sender: AnyObject) {
let error = Locksmith.deleteDataForUserAccount("tgsLoginUser", inService: "tgsLogin")
self.performSegueWithIdentifier("logoutViewSegue", sender: self)
}
#IBAction func textFieldReturn(sender: AnyObject) {
sender.resignFirstResponder()
mapView.removeAnnotations(mapView.annotations)
self.performSearch()
}
func performSearch() {
matchingItems.removeAll()
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = searchText.text
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler({(response:
MKLocalSearchResponse!,
error: NSError!) in
if error != nil {
println("Error occured in search: \(error.localizedDescription)")
} else if response.mapItems.count == 0 {
println("No matches found")
} else {
println("Matches found")
for item in response.mapItems as [MKMapItem] {
println("Name = \(item.name)")
println("Phone = \(item.phoneNumber)")
self.matchingItems.append(item as MKMapItem)
println("Matching items = \(self.matchingItems.count)")
var annotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
self.mapView.addAnnotation(annotation)
}
}
})
}
override func viewDidLoad() {
super.viewDidLoad()
mapView.showsUserLocation = true
mapView.delegate = self
}
}
app delegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var locationManager: CLLocationManager?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
return true
}
The error message suggests that you may be somewhere using searchText as if it was a function. I don't see that in your code, so there are several possibilities:
You have some other code that uses it that you did not post
The binary is not in sync with the source code above
There is a bug in the framework
I would focus on the first two. Try reviewing all error messages to see if there is any indication of line in the code that fails. Try cleaning the project and rebuilding. Try searching for "searchText" in all your source files...
This is the code that worked for me. The only differences I see is some question marks instead of exclamation points. Let me know if this works for you.
#IBAction func textFieldReturn(sender: AnyObject) {
sender.resignFirstResponder()
mapView.removeAnnotations(mapView.annotations)
self.performSearch()
}
func performSearch() {
matchingItems.removeAll()
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = searchText.text
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler({
(response: MKLocalSearchResponse?,error: NSError?) in
if error != nil {
print("Error occured in search: \(error!.localizedDescription)")
} else if response!.mapItems.count == 0 {
print("No matches found")
} else {
print("Matches found")
for item in response!.mapItems {
print("Name = \(item.name)")
print("Phone = \(item.placemark)")
self.matchingItems.append(item as MKMapItem)
print("Matching items = \(self.matchingItems.count)")
let annotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
annotation.subtitle = address
self.mapAnnotations.append(annotation)
self.mapView.addAnnotation(annotation)
}
}
})
}

Resources