display multiple annotations on mapview - arrays

I've been looking around on stackoverflow for a solution but I haven't yet successfully implemented it. If someone can give me some tips on where the problem lies, thank you so much. Here is what I have so far
Here is location class
class Location: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
Method to display all annotations.
func displayAllEventsPins() {
for event in events {
let address = event.location
geocoder.geocodeAddressString(address!, completionHandler: { (placemarks: [CLPlacemark]?, error: Error?) -> Void in
if let placemark = placemarks?.first {
let eventlat = placemark.location?.coordinate.latitude
let eventlong = placemark.location?.coordinate.longitude
let annotation = MKPointAnnotation()
annotation.title = event.name
annotation.coordinate = CLLocationCoordinate2D(latitude: eventlat!, longitude: eventlong!)
self.locations.append(Location(title: annotation.title!, coordinate: annotation.coordinate))
for location in self.locations {
let pin = MKPointAnnotation()
pin.title = location.title
pin.coordinate = location.coordinate
self.mapView.addAnnotation(pin)
}
}
})
}
}
Edited: The problem here is that annotations doesnt show up on mapview. I can only see the currentlocation pin and nothing else.
Edited: This is the call i used to drop user current location pin.
extension Search : CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//MARK: remove previous current pin for user location
mapView.removeAnnotation(newPin)
let location = locations.last! as CLLocation
let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
self.currentLocation = location
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.03, 0.03))
mapView.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
mapView.addAnnotation(newPin)
}
}
Here is the code in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
//MARK: Request Current Location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.requestLocation()
displayAllEventsPins()
}

This should work for you.
By the way, looping through your locations whilst in the events loop is just going to add duplicates of the same pin, which will be very bad on memory and it's not a good thing to do.
import UIKit
import MapKit
import Firebase
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
var events = Array<Event>()
var locations = Array<Location>()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// This closure gets called once for every event in your database
getEvents { (event, pin) in
self.tableView.reloadData()
if event != nil && pin != nil {
print(event!)
self.locations.append(pin!)
self.events.append(event!)
} else {
print("Failed to get event.")
}
}
}
func getEvents(results: #escaping (_ event: Event?, _ pin:Location?)->()) {
let ref = FIRDatabase.database().reference().child("Events")
ref.observe(.childAdded, with: { (snapshot) in
guard let value = snapshot.value as? Dictionary<String,String> else { return }
guard let name = value["eventName"],
let location = value["location"],
let attending = value["attendance"],
let dateTime = value["dateTime"],
let addedByUser = value["addedByUser"] else { return }
self.getEventPlacemark(address: location, results: { (placemark) in
if let placemark = placemark {
let pin = Location(title: name, coordinate: placemark.coordinate)
var distance: Double = -1 // If user location is not avalible, this will stay at -1
if let currentLocation = self.locationManager.location?.coordinate {
distance = pin.coordinate.distance(to: currentLocation)
}
let event = Event(id: snapshot.key, name: name, location: location, dateTime: dateTime, addedByUser: addedByUser, attending: attending, distance: distance)
results(event, pin)
return
}
})
})
}
func getEventPlacemark(address:String, results: #escaping (_ placemark: MKPlacemark?)->()){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
if let error = error {
print(error.localizedDescription)
results(nil)
}
if let placemark = placemarks?.first {
results(MKPlacemark(placemark: placemark))
}
}
}
func displayAllEvents(){
self.map.addAnnotations(self.locations)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let userLocation = annotation as? MKUserLocation {
let view = (mapView.dequeueReusableAnnotationView(withIdentifier: "userLocationPin") as? MKPinAnnotationView) ?? MKPinAnnotationView(annotation: userLocation, reuseIdentifier: "userLocationPin")
view.pinTintColor = .purple
view.canShowCallout = true
return view
}
if let pin = annotation as? MKPointAnnotation {
let view = (mapView.dequeueReusableAnnotationView(withIdentifier: "pin") as? MKPinAnnotationView) ?? MKPinAnnotationView(annotation: pin, reuseIdentifier: "pin")
view.pinTintColor = .red
view.canShowCallout = true
return view
}
return nil
}
}
class Location: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
}
struct Event {
var name: String
var location: String
}
extension CLLocationCoordinate2D {
func distance(to: CLLocationCoordinate2D) -> CLLocationDistance {
return MKMetersBetweenMapPoints(MKMapPointForCoordinate(self), MKMapPointForCoordinate(to))
}
}
If you are going to implement my code above, you'll need to remove your code from
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
because you don't need to add the pin manually anymore.
Can you try putting this in your view did load function and not have anything else run. This should put a pin to the west of Africa.
Something to notice, if the coordinate is
CLLocationCoordinate2D(latitude: 0, longitude: 0), the pin appears
right down at Antartica on the date line, which is the bottom right of
the map. So if for some reason your coordinate is the default 0,0,
your pins might by sitting there.
let pin = MKPointAnnotation()
pin.title = "Null Island"
pin.coordinate = CLLocationCoordinate2DMake(0.000001, 0.000001)
self.map.addAnnotation(pin)
This could possibly be where your pins are.

Related

My firebase data is geting fetched but is not appending into my array? [duplicate]

Currently I am attempting to push values into an array of note objects from firebase
The only issue is due to Firebases asynchronous nature, I am having trouble getting the main thread to wait until the fetch function is completed. I have viewed many answers on this site and I have read up on the Semaphores and Dispatch queue documentation however I cannot get this fetch to work. It appears that most of the people here are attempting to use a table view which I am not.
Here is the fetch code
func fetchUser(){
FIRDatabase.database().reference().child("notes").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = noteClass(dictionary: dictionary)
self.coordinotes.append(user)
}
}, withCancel: nil)
}
I have removed all of my semaphore and dispatch main attempts due to none of them working. This function is called in my view did load. When i check the values of my array that i push them into 'coordinotes' the value is not yet placed in and i get an out of bounds error.
Rest of code
import UIKit
import MapKit
import CoreLocation
import Firebase
import FirebaseDatabase
struct PreferencesKeys{
static let savedItems = "savedItems"
}
class ViewController: UIViewController, CLLocationManagerDelegate{
let manager = CLLocationManager()
var coordinotes:[noteClass] = Array()
var latitude = Double()
var noteTime = noteBrain()
//Map
#IBOutlet weak var map: MKMapView!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations[0]
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, noteTime.span)
map.setRegion(region, animated: true)
self.map.showsUserLocation = true
}
override func viewDidLoad()
{
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
if FIRAuth.auth()?.currentUser?.uid == nil {
perform(#selector(handleLogout), with: nil, afterDelay: 0)
}
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
fetchUser()
loadAllCoordinotes()
}
func handleLogout() {
do {
try FIRAuth.auth()?.signOut()
} catch let logoutError {
print(logoutError)
}
let loginController = LoginController()
present(loginController, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func loadAllCoordinotes() {
let length = coordinotes.count - 1
map.addAnnotation(coordinotes[length])
}
func fetchUser(_ completion:#escaping ([noteClass] , _ success: Bool)-> Void){
let coordinotes = [noteClass]()
FIRDatabase.database().reference().child("notes").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = noteClass(dictionary: dictionary)
coordinotes.append(user)
}
completion(coordinotes, true)
}, withCancel: nil)
}
and then you call it in viewDidLoad like this:
fetchUser { (coordinotes, success) in
if success {
self.coordinotes = coordinote
self.loadAllCoordinotes()
}
}

Duplicating last row of table when new value entered

I have a chat feature within my app. The page loads the existing data as an array called hhmessages. The last message in the conversation was 'Welcome', when I enter new text 'Thank You' and hit enter the table automatically displays 'Welcome' again instead of 'Thank You.' If it exit out of the page and come back it now shows 'Thank You' as the last message. It's working on the backend just the instant update isn't showing the value in the UITableView when entered.
This is for an iPhone app.
UPDATED TO SHOW COMPLETE CODE - Now that reverse has been removed the new entry shows as blank.
import UIKit
import Foundation
extension String {
// Calculeta the hight string Function
func calculateTextFrameRect(
objectsInPlaceHeight: CGFloat,
objectsInPlaceWidth: CGFloat,
fontSize: CGFloat,
fontWeight: CGFloat) -> CGSize
{
let bounding = CGSize(width: UIScreen.main.bounds.width - objectsInPlaceWidth, height: .infinity)
let rect = NSString(string: self).boundingRect(
with: bounding,
options: NSStringDrawingOptions.usesFontLeading.union(NSStringDrawingOptions.usesLineFragmentOrigin),
attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize, weight: UIFont.Weight(rawValue: fontWeight))],
context: nil)
return CGSize(width: UIScreen.main.bounds.width, height: rect.height + objectsInPlaceHeight )
}
}
// Messages for test
let frame = CGRect(origin: .zero, size: CGSize.init(width: 375, height: 559))
class Message {
let message: String
var incoming: [Int]
let image: UIImage
var avas = UIImage()
init(message: String, image: UIImage, incoming: Int, avas: UIImage) {
self.message = message
self.image = image
self.incoming = [incoming]
self.avas = avas
}
}
class ConversationViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
//var user = NSDictionary()
var messages = NSDictionary()
//var guest = NSDictionary()
#IBOutlet var senderLbl: UILabel!
#IBOutlet var senderageLbl: UILabel!
#IBOutlet var senderraceLbl: UILabel!
#IBOutlet var sendergenderLbl: UILabel!
#IBOutlet var sendercityLbl: UILabel!
#IBOutlet var senderstateLbl: UILabel!
// #IBOutlet var tableView: UITableView!
var hhmessages = [AnyObject]()
//var messages: [Message] = []
var pictures = [UIImage]()
var avas = [UIImage]()
var avaURL = [String]()
var isLoading = false
var skip = 0
var limit = 50
var images = [UIImage]()
var incoming: [Int] = []
var comments = [String]()
var ids = [String]()
//var isSent: String = ""
var isPictureSelected = false
//var currentUser_ava = [Any]()
#IBOutlet var pictureImg: UIImageView!
#IBOutlet var avaImg: UIImageView!
#IBOutlet var viewprofile_btn: UIButton!
#IBOutlet var imgprofile_btn: UIButton!
#IBOutlet var replyTxt: UITextView!
//var replyTxt:UITextView!
#IBOutlet var replyTxt_height: NSLayoutConstraint!
#IBOutlet var replyTxt_bottom: NSLayoutConstraint!
#IBOutlet var picSelect: UIButton!
#IBOutlet var replyBtn: UIButton!
var puuid = String()
var imageSelected = false
var coolIndicator: UIActivityIndicatorView!
var commentsTextView_bottom_identity = CGFloat()
#IBOutlet var tableView: UITableView!
// Table View here + basic configuration
override func viewDidLoad() {
//self.tabBarController?.tabBar.isHidden = true
super.viewDidLoad()
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
// dynamic cell height
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 200
loadPosts()
replyTxt.layer.cornerRadius = replyTxt.bounds.width / 50
replyTxt.backgroundColor = UIColor.clear
replyTxt.layer.borderColor = UIColor.gray.cgColor
replyTxt.layer.borderWidth = 1.0
let username = messages["sender"] as? String
self.navigationItem.title = username
}
// pre last func
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// remove observers of notification when the viewController is left
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
// exec-d once notification is caught -> KeyboardWillShow
#objc func keyboardWillShow(_ notification: Notification) {
// getting the size of the keyboard
if let keyboard_size = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
// increasing the bottom constraint by the keyboard's height
replyTxt_bottom.constant += keyboard_size.height
}
// updating the layout with animation
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
// exec-d once notification is caught -> KeyboardWillHide
#objc func keyboardWillHide() {
// updating the layout with animation
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//replyTxt().resignFirstResponder()
self.view.endEditing(false)
}
// TABLEVIEW
// Number os cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return hhmessages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let colorSmoothGray = UIColor(red: 229/255, green: 229/255, blue: 234/255, alpha: 1)
let colorBrandBlue = UIColor(red: 148 / 255, green: 33 / 255, blue: 147 / 255, alpha: 1)
let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
print("test 1", pictureURL)
// no picture in the post
if pictureURL == nil || pictureURL == "" {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ConversationCell
cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
// shortcuts
let hhpost = hhmessages[indexPath.row]
let text = hhpost["messagetext"] as? String
cell.messageLbl.text = text
cell.messageLbl.textAlignment = .right
cell.messageLbl.backgroundColor = colorSmoothGray
cell.messageLbl.textColor = .black
cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
cell.messageLbl.font?.withSize(25)
cell.messageLbl.clipsToBounds = true
cell.messageLbl.sizeToFit()
pictures.append(UIImage())
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "PicCell", for: indexPath) as! PicConversationCell
cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
let smimages = hhmessages[indexPath.row]["path"] as? UIImage
cell.smavaImg.image = smimages
for i in 0 ..< self.incoming.count {
// Confiture the constraints for cell
if self.incoming[indexPath.row] == 1 {
// Text
cell.messageLbl.textAlignment = .left
cell.messageLbl.backgroundColor = colorBrandBlue
cell.messageLbl.textColor = .white
cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
cell.messageLbl.font?.withSize(25)
cell.messageLbl.clipsToBounds = true
// Constraints
cell.lefBubbleConstraint.isActive = true
cell.rightBubbleConstraint.isActive = false
if cell.postpictureImg.image == nil {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
else {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
}
else if self.incoming[indexPath.row] == 0 {
// Text
cell.messageLbl.textAlignment = .right
cell.messageLbl.backgroundColor = colorSmoothGray
cell.messageLbl.textColor = .black
cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
cell.messageLbl.font?.withSize(25)
cell.messageLbl.clipsToBounds = true
// Constraints
cell.lefBubbleConstraint.isActive = false
cell.rightBubbleConstraint.isActive = true
if cell.postpictureImg.image == nil {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
else {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
}
if cell.lefBubbleConstraint.isActive == true {
cell.lefImageConstraint.isActive = true
cell.rightImageConstraint.isActive = false
} else {
cell.lefImageConstraint.isActive = false
cell.rightImageConstraint.isActive = true
}
let pictureString = hhmessages[indexPath.row]["uploadpath"] as! String
let pictureURL = URL(string: pictureString)!
// if there are still pictures to be loaded
if hhmessages.count != pictures.count {
URLSession(configuration: .default).dataTask(with: pictureURL) { (data, response, error) in
// downloaded
if let image = UIImage(data: data!) {
self.pictures.append(image)
DispatchQueue.main.async {
cell.postpictureImg.image = image
}
}
}.resume()
// cached picture
} else {
DispatchQueue.main.async {
cell.postpictureImg.image = self.pictures[indexPath.row]
}
}
}
return cell
}
}
// pre load func
override func viewDidAppear(_ animated: Bool) {
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
// func of loading posts from server
#objc func loadPosts() {
//isLoading = true
let me = user!["username"] as! String
let meid = user!["id"] as! String
print(meid)
print(me)
//print(username)
let uuid = messages["uuid"] as! String
print(uuid)
// accessing php file via url path
let url = URL(string: "http://localhost/message.php")!
// pass information to php file
let body = "username=\(me)&uuid=\(uuid)&recipient_id=\(meid)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = body.data(using: String.Encoding.utf8)
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
// launch session
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// no error of accessing php file
// error occured
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
//self.isLoading = false
return
}
do {
// access data - safe mode
guard let data = data else {
Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
//self.isLoading = false
return
}
// getting content of $returnArray variable of php file
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary
// accessing json data - safe mode
guard let posts = json?["messages"] as? [NSDictionary] else {
//self.isLoading = false
return
}
// assigning all successfully loaded posts to our Class Var - posts (after it got loaded successfully)
self.hhmessages = posts
self.tableView.reloadData()
// scroll to the latest index (latest cell -> bottom)
let indexPath = IndexPath(row: self.hhmessages.count - 1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
// self.isLoading = false
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
//self.isLoading = false
return
}
}
}.resume()
}
#IBAction func viewprofile_clicked(_ sender: Any) {
// performSegue(withIdentifier: "guest2", sender: self.guest)
}
#IBAction func imgprofile_clicked(_ sender: Any) {
// performSegue(withIdentifier: "guest2", sender: self.guest)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "guest" {
if let destination = segue.destination as? GuestViewController {
destination.guest = messages
}
}
}
// function sending requset to PHP to uplaod a file
func uploadPost() {
// validating vars before sending to the server
guard let user_id = user?["id"] as? String, let username = user?["username"] as? String, let avaPath = user?["ava"] else {
// converting url string to the valid URL
if let url = URL(string: user?["ava"] as! String) {
// downloading all data from the URL
guard let data = try? Data(contentsOf: url) else {
return
}
// converting donwloaded data to the image
guard let image = UIImage(data: data) else {
return
}
// assigning image to the global var
let currentUser_ava = image
}
return
}
let user_id_int = Int(user_id)!
let messagetext = replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines)
hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
replyTxt.text = ""
textViewDidChange(replyTxt)
let recipient = messages["username"] as! String
let rid = String(describing: messages["recipient_id"]!)
let uuid = messages["uuid"] as! String
puuid = UUID().uuidString
// prepare request
let url = URL(string: "http://localhost/messagepost.php")!
let body = "sender_id=\(user_id)&sender=\(username)&text=\(messagetext)&recipient_id=\(rid)&recipient=\(recipient)&uuid=\(uuid)&puuid=\(puuid)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = body.data(using: .utf8)
// send request
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// error happened
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
return
}
do {
// converting received data from the server into json format
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
// safe mode of casting json
guard let parsedJSON = json else {
return
}
// if the status of JSON is 200 - success
if parsedJSON["status"] as! String == "200" {
} else {
Helper().showAlert(title: "400", message: parsedJSON["status"] as! String, in: self)
return
}
// json error
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
return
}
}
}.resume()
}
// exec-d whenever delegated textView has been changed by chars
func textViewDidChange(_ textView: UITextView) {
// declaring new size of the textView. we increase the height
let new_size = textView.sizeThatFits(CGSize.init(width: textView.frame.width, height: CGFloat(MAXFLOAT)))
// assign new size to the textView
textView.frame.size = CGSize.init(width: CGFloat(fmaxf(Float(new_size.width), Float(textView.frame.width))), height: new_size.height)
//UIView.animate(withDuration: 0.2) {
self.view.layoutIfNeeded()
//}
}
#IBAction func picSelect_clicked(_ sender: AnyObject) {
// calling picker for selecting iamge
showActionSheet()
}
// this function launches Action Sheet for the photos
func showActionSheet() {
// declaring action sheet
let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// declaring camera button
let camera = UIAlertAction(title: "Camera", style: .default) { (action) in
// if camera available on device, than show
if UIImagePickerController.isSourceTypeAvailable(.camera) {
self.showPicker(with: .camera)
}
}
// declaring library button
let library = UIAlertAction(title: "Photo Library", style: .default) { (action) in
// checking availability of photo library
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
self.showPicker(with: .photoLibrary)
}
}
// declaring cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
// adding buttons to the sheet
sheet.addAction(camera)
sheet.addAction(library)
sheet.addAction(cancel)
// present action sheet to the user finally
self.present(sheet, animated: true, completion: nil)
}
// takes us to the PickerController (Controller that allows us to select picture)
func showPicker(with source: UIImagePickerControllerSourceType) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = source
present(picker, animated: true, completion: nil)
}
// executed whenever the image has been picked via pickerController
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// accessing selected image
let image = info[UIImagePickerControllerEditedImage] as? UIImage
// assigning selected image to pictureImageView
pictureImg.image = image
// cast boolean as TRUE -> Picture Is Selected
isPictureSelected = true
// remove pickerController
pictureImg.image = info[UIImagePickerControllerEditedImage] as? UIImage
self.dismiss(animated: true, completion: nil)
// cast as a true to save image file in server
if pictureImg.image == info[UIImagePickerControllerEditedImage] as? UIImage {
imageSelected = true
}
dismiss(animated: true, completion: nil)
}
// exec when pictureImageView has been tapped
#IBAction func pictureImageView_tapped(_ sender: Any) {
// declaring action sheet
let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// declaring delete button
let delete = UIAlertAction(title: "Delete", style: .destructive) { (action) in
self.pictureImg.image = UIImage()
}
// declaring cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
// adding buttons to the sheet
sheet.addAction(delete)
sheet.addAction(cancel)
// present action sheet to the user finally
self.present(sheet, animated: true, completion: nil)
}
// custom body of HTTP request to upload image file
func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
// if file is not selected, it will not upload a file to server, because we did not declare a name file
var filename = ""
if imageSelected == true {
filename = "notes-\(puuid).jpg"
}
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body as Data
}
#IBAction func replyBtn_clicked(_ sender: Any) {
if replyTxt.text.isEmpty == false && replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false {
uploadPost()
//tableView.reloadData()
}
}
#objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
//print("deltaY",deltaY)
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.replyTxt.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
self.tableView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
self.replyBtn.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
self.picSelect.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
},completion: nil)
}
func textFieldShouldReturn(_ replyTxt: UITextField) -> Bool {
replyTxt.resignFirstResponder()
return true
}
}
the problem is you are inserting the new text at
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)
which is the last field of the array.
but in your cellForRow: you have
let text = hhmessages.reversed()[indexPath.row]["messagetext"] as! String
which shows the first field of your array in the last cell of tableView.
I think thats your problem.
Like others have told, you are messing up your order in hhmessages.
Imagine you have messages Welcome, Hello, and you are trying to add Thank Your, your code with more comments:
self.hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex) // Thank You is inserted to the end of the array at 3rd position (2)
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0) // ok, let's get index of 3rd row (2)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic) // add new row to the end
tableView.endUpdates()
Then later UIKit asks you to load this new 3rd row at position 2, and you call:
let text = hhmessages.reversed()[indexPath.row]["messagetext"] as! String
The problem is hhmessages.reversed() which reverses your array, and makes Thank you in fact first at position 0, and Welcome the last one at position 2, which will get the text Welcome.
The second problem I see is this line:
let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
Here you are getting unreveresed picture url, which at least is very strange.

Pass an arrays row shown in an NSTableView to another array in Swift

I have 2 arrays
var messages = [Message]()
var screenMessages = [screenMessage]()
I have the messages array items in a NSTableView.. when I press an IBOutlet I would like to pass the items in that row to the screenMessages array to present in another NSTableView.
My NSTableView starts like so..
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell
let mess = messages[row]
I've tried a number of ways of appending the screenMessages with the messages[row] but I can't put my finger on it. If anyone could demonstrate or point me in the right direction that would be brilliant.
Thank you.
Added more detail:
Screen one looks like so and when pressing the add button it should then pass that data from that row into screen twos tableview..
Screen two:
My View for screen one is as:
import Firebase
import Cocoa
var messages = [Message]()
var screenMessages = [screenMessage]()
class secondVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var screenRefreshBtn: NSButton!
#IBOutlet weak var refreshButton: NSButton!
var senderImageUrl: String!
var ref: Firebase!
var messagesRef: Firebase!
func setupFirebase() {
messagesRef = Firebase(url: "https://url.firebaseio.com/screenmessages")
messagesRef.queryLimitedToLast(25).observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in
let text = snapshot.value["text"] as? String
let sender = snapshot.value["senderName"] as? String
let imageUrl = snapshot.value["profileImageURL"] as? String
let MediaType = snapshot.value["MediaType"] as! String
let fileUrl = snapshot.value["fileUrl"] as? String
let message = Message(text: text, sender: sender, imageUrl: imageUrl, MediaType: MediaType, fileUrl: fileUrl)
messages.append(message)
let screenmessage = screenMessage(text: text, sender: sender, imageUrl: imageUrl, MediaType: MediaType, fileUrl: fileUrl)
screenMessages.append(screenmessage)
switch MediaType{
case "TEXT":
print("text message")
case "PHOTO":
print("photo message")
default:
print("default")
}
self.tableView.reloadData()
})
}
override func viewDidLoad() {
super.viewDidLoad()
setupFirebase()
}
// MARK: - Table View
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return messages.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell
let mess = messages[row]
if mess.text() == nil {
result?.textField?.alphaValue = 0
result!.sendertextView.stringValue = mess.sender()
let url = NSURL(string: mess.fileUrl()!)!
// Download task:
// - sharedSession = global NSURLCache, NSHTTPCookieStorage and NSURLCredentialStorage objects.
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
// if responseData is not null...
if let data = responseData{
// execute in UI thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let photo = NSImage(data: data)!
result?.mediaPhoto.image = photo
})
}
}
task.resume()
} else {
result!.textField!.stringValue = mess.text()!
result!.sendertextView.stringValue = mess.sender()
}
return result
}
#IBAction func addtablerow(object: NSButton) {
let row = tableView.rowForView( object as NSView )
if ( row > -1 ) {
}
}
And my second screen is:
import Cocoa
class screenVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
var addedObserver = false
#IBOutlet weak var tableView: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
refreshObs()
clearObs()
self.tableView.backgroundColor = NSColor.clearColor()
if let window = self.view.window {
// custom window here
window.level = Int(CGWindowLevelForKey(.FloatingWindowLevelKey))
} else {
addedObserver = true
self.addObserver(self, forKeyPath: "view.window", options: [.New, .Initial], context: nil)
}
}
func refreshList(notification: NSNotification){
self.tableView.alphaValue = 0
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
animateViewRefresh()
tableView.scrollToEndOfDocument(self)
}
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return screenMessages.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell2", owner: self) as? screenviewTableCell
let mess = screenMessages[row]
result?.senderLabel.stringValue = mess.sender()
if mess.text() != nil {
result?.messageTextView.stringValue = mess.text()!
let url = NSURL(string: mess.imageUrl()!)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
result?.avatarImage.image = NSImage(data: data)
})
}}
task.resume()
} else {
result?.messageTextView.alphaValue = 0
let mess = screenMessages[row]
let url = NSURL(string: mess.fileUrl()!)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let photo = NSImage(data: data)!
result?.mediaPhoto.image = photo
})
}
}
let url2 = NSURL(string: mess.imageUrl()!)!
let task2 = NSURLSession.sharedSession().dataTaskWithURL(url2) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
result?.avatarImage.image = NSImage(data: data)
})
}}
task.resume()
task2.resume()
}
return result
}
// MARK : Animate
func animateView(notification: NSNotification){
NSAnimationContext.runAnimationGroup({ (context) in
context.duration = 2
self.tableView.animator().alphaValue = 0
screenMessages.removeAll()
}, completionHandler: { () -> Void in
})}
func animateViewRefresh(){
NSAnimationContext.runAnimationGroup({ (context) in
context.duration = 4
self.tableView.animator().alphaValue = 1
}, completionHandler: { () -> Void in
})}
func refreshObs(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(screenVC.refreshList(_:)), name:"refreshMyTableView", object: nil)
}
func clearObs(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(screenVC.animateView(_:)), name:"clearMyTableView", object: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let window = self.view.window {
// custom window here
window.level = Int(CGWindowLevelForKey(.FloatingWindowLevelKey))
window.titlebarAppearsTransparent = true
window.movableByWindowBackground = true
window.opaque = true
window.backgroundColor = NSColor.clearColor()
}
}
deinit {
if addedObserver {
self.removeObserver(self, forKeyPath: "view.window")
}
}
}
I have tried a number of things such as 'screenMessages += messages(row)' and appending to add that row to the screenMessages array but I've had no luck.
Am I going about this in the right way or is there a better way of doing so?
Thank you.
To append an element from one array to another array just write
let index = index of element you need
let message = messages[index]
screenMessages.append(message)
If message is not the same type as the contents of the screenMessages array you will need to convert it, I would need more details of the types to help with that.
If you are having trouble passing the data to another ViewController I would need more information on the current architecture to give good advice, but for example you might define a protocol MessageDelegate that one of the controllers implements and the other has as a property.
update
If you update your data array for a table and want the new information to appear remember to call reloadData on the UITableView

How to loop data in JSON When string in label equal data in JSON array

I need to show data from JSON on label. But my code get error.please help me see on function barcodeReaded. How to loop data when String in label equal string in "testCode" on array JSON file.
This JSON file
{
"episode": [
{
"testCode": "11111111",
"title": "Stomachic mixture 180 ml",
"drug": "AAAAA",
"thumbnailURL": "https://firebasestorage.googleapis.com/v0/b/rxscan-a14ee.appspot.com/o/j01.jpg?alt=media&token=5718797b-fc9c-416e-9394-b544c2880dc9",
"price": "100"
},
{
"testCode": "22222222",
"title": "Parasetamol 200 ml",
"drug": "BBBBB",
"thumbnailURL": "urlImage",
"price": "150"
},
{
"testCode": "33333333",
"title": "Beramol 300 ml",
"drug": "CCCCC",
"thumbnailURL": "urlImage",
"price": "120"
}
]
}
This some code
import UIKit
class barcodeViewController: UIViewController, BarcodeDelegate {
#IBOutlet weak var thumbnailImageView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var drugLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var showCodeLabel: UILabel!
var episode: Episode!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
print("Segue!")
let barcodeViewController: barcodeCapViewController = segue.destinationViewController as! barcodeCapViewController
barcodeViewController.delegate = self
}
#IBAction func doneButtonPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func barcodeReaded(barcode: String) {
print("Barcode is: \(barcode)")
showCodeLabel.text = barcode
barcode = episode.testCode
if((episode.testCode) != nil)
{
titleLabel.text = episode.title
drugLabel.text = episode.drug
priceLabel.text = episode.price
}
}
}
import Foundation
class Episode
{
var title: String?
var thumbnailURL: NSURL?
var drug: String?
var price: String?
var testCode: String?
init(title: String, thumbnailURL: NSURL, drug: String, price: String, testCode: String)
{
self.title = title
self.thumbnailURL = thumbnailURL
self.drug = drug
self.price = price
self.testCode = testCode
}
typealias EpisodeDictionary = [String : AnyObject]
init(espDictionary: EpisodeDictionary)
{
self.title = espDictionary["title"] as? String
self.thumbnailURL = NSURL(string: espDictionary["thumbnailURL"] as! String)
self.drug = espDictionary["drug"] as? String
self.price = espDictionary["price"] as? String
self.testCode = espDictionary["testCode"] as? String
}
static func downloadAllEpisodes() -> [Episode]
{
var episodes = [Episode]()
let jsonFile = NSBundle.mainBundle().pathForResource("testJson3edit6", ofType: "json")
let jsonData = NSData(contentsOfFile: jsonFile!)
if let jsonDictionary = NetworkService.parseJSONFromData(jsonData) {
let espDictionaries = jsonDictionary["episodes"] as! [EpisodeDictionary]
for dict in espDictionaries {
let episode = Episode(espDictionary: dict)
episodes.append(episode)
}
}
return episodes
}
}
NetworkService.swift
import Foundation
class NetworkService
{
// TODO: Make this class be able to download images from a URL
lazy var configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
lazy var session: NSURLSession = NSURLSession(configuration: self.configuration)
let url: NSURL
init(url: NSURL)
{
self.url = url
}
func downloadImage(completion: (NSData -> Void))
{
let request = NSURLRequest(URL: self.url)
let dataTask = session.dataTaskWithRequest(request) { (data, response, error) in
if error == nil {
if let httpResponse = response as? NSHTTPURLResponse {
switch (httpResponse.statusCode) {
case 200:
if let data = data {
completion(data)
}
default:
print(httpResponse.statusCode)
}
}
} else {
print("Error download data: \(error?.localizedDescription)")
}
}
dataTask.resume()
}
}
extension NetworkService
{
static func parseJSONFromData(jsonData: NSData?) -> [String : AnyObject]?
{
if let data = jsonData {
do {
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String : AnyObject]
return jsonDictionary
} catch let error as NSError {
print("Error processing json data: \(error.localizedDescription)")
}
}
return nil
}
}
This code for get image that use in detailViewController
if episode.thumbnailURL != nil {
if let thumbnailURL = episode.thumbnailURL {
let networkService = NetworkService(url: thumbnailURL)
networkService.downloadImage({ (data) in
//thumbnailImageView.image = episode.thumbnailURL
let image = UIImage(data: data)
dispatch_async(dispatch_get_main_queue(), {
self.thumbnailImageView.image = image
})
})
}
}
You can get detail of your barcode like this from your array of dictionary.
func barcodeReaded(barcode: String) {
print("Barcode is: \(barcode)")
showCodeLabel.text = barcode
let episodes = Episode.downloadAllEpisodes()
var filteredEpisodes = episodes.filter({ $0.testCode == barcode })
if filteredEpisodes.count > 0 {
titleLabel.text = filteredEpisodes[0].title
drugLabel.text = filteredEpisodes[0].drug
priceLabel.text = filteredEpisodes[0].price
}
}
Try it. Hope it may help you.
var resultData = NSDictionary()
var episode = NSArray()
func loadDataFromJSON(){
// put your json to resultData
// Now resultData holds whole json object
// get episode array from resultData
episode = resultData.objectForKey("episode") as! NSArray
}
func traverseThroughEpisode(){
for i in 0..< episode.count {
// retrive testCode like that & set it whatever you want
let testCode = episode.objectAtIndex(i).objectForKey("testCode") as! String
}
}

Returning an array of objects from a function

I'm new to Swift.
I have the following classes used to map a GET JSON response.
class BasketballTeamResponse: Mappable {
var name: String?
var alias: String?
var market: String?
var founded: Int?
var players: [Players]?
required init?(_ map: Map){ }
func mapping(map: Map) {
name <- map["name"]
alias <- map["alias"]
market <- map["market"]
founded <- map["founded"]
players <- map["players"]
}
}
class Players: Mappable {
var full_name: String?
var jersey_number: String?
var position: String?
init(full_name: String, jersey_number: String, position: String) {
self.full_name = full_name
self.jersey_number = jersey_number
self.position = position
}
required init?(_ map: Map) { }
func mapping (map: Map) {
full_name <- map["full_name"]
jersey_number <- map["jersey_number"]
position <- map["position"]
}
}
Let's say I have a ViewController and I want to populate finalRoster with an array of objects of Players. I've tried the appending with self and finalRoster is still empty and I want to use this later on to display them in a tableview. I even tried setting the return type to -> [Players]
class ViewController: UIViewController {
var finalRoster = [Players]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
getBasketBallTeamPlayers()
}
private func getBasketBallTeamPlayers() {
let URL = "http://api.sportradar.us/nba-t3/teams/583ec825-fb46-11e1-82cb-f4ce4684ea4c/profile.json?api_key=xxxxxxxxxxxxxxxxxxxxxxxx"
//var pool = [Players]()
Alamofire.request(.GET, URL, parameters: nil)
.validate()
.responseObject { (response: Response<BasketBallTeamResponse, NSError>) in
let gswResponse = response.result.value
if let roster = gswResponse?.players {
for players in roster {
print(players.full_name!)
print(players.jersey_number!)
print(players.position!)
let add = Players(full_name: players.full_name!, jersey_number: players.jersey_number!, position: players.position!)
self.finalRoster.append(add)
}
}
}
}
How can I pass the array of objects from getBasketBallTeamPlayers() to finalRoster? Thanks
As jtbandes have comment it's better to call the class Player instead of Players.
typealias apiSuccess = (result: Player?) -> Void
typealias apiFailure = (error: NSDictionary?) -> Void
class ViewController: UIViewController {
var finalRoster = [Player]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let myApiSuccess: apiSuccess = {(result: Player?) -> Void in
print ("Api Success : result is:\n \(result)")
// Here you can make whatever you want with result
self.finalRoster.append(result!)
}
let myApiFailure: apiFailure = {(error: NSDictionary?) -> Void in
print ("Api Failure : error is:\n \(error)")
// Here you can check the errors with error dictionary looking for http error type or http status code
}
getBasketBallTeamPlayers(success: myApiSuccess, failure: myApiFailure)
}
private func getBasketBallTeamPlayers(success successBlock :apiSuccess,
failure failureBlock :apiFailure) {
let URL = "http://api.sportradar.us/nba-t3/teams/583ec825-fb46-11e1-82cb-f4ce4684ea4c/profile.json?api_key=xxxxxxxxxxxxxxxxxxxxxxxx"
//var pool = [Players]()
Alamofire.request(.GET, URL, parameters: nil)
.validate()
.responseObject { (response: Response<BasketBallTeamResponse, NSError>) in
if response.result.isSuccess {
let gswResponse = response.result.value
if let roster = gswResponse?.players {
for players in roster {
print(players.full_name!)
print(players.jersey_number!)
print(players.position!)
let add = Players(full_name: players.full_name!, jersey_number: players.jersey_number!, position: players.position!)
successBlock(result: add)
}
} else {
print("I have some kind of error in my data")
}
} else {
let httpError: NSError = response.result.error!
let statusCode = httpError.code
let error:NSDictionary = ["error" : httpError,"statusCode" : statusCode]
failureBlock(error: error)
}
}
}
}

Resources