Swift 2 , CLGeocoder() and placemarks - xcode

I want to get the address of the GPS signal and I write that code: `
CLGeocoder().reverseGeocodeLocation(userLocation) { (placemarks, error) -> Void in
if error != nil {
print("Κάτι δεν πήγε καλά με το GPS!")
} else {
if let p = CLPlacemark(placemark: placemarks?[0] as! CLPlacemark) {
print(p)
}
}
The error is that: Downcast from 'CLPlacemark?' to 'CLPlacemark' only unwraps optionals; did you mean to use '!'? . Where do I have the error?

No need to initialize a CLPlacemark like this. This async method returns an array of CLPlacemarks and this array is optional. So you need to unwrap the array if it exists and return the first element of that array which is already a CLPlacemark.
if let validPlacemark = placemarks?[0]{
print(validPlacemark)
}
'[CLPlacemark]?' is not convertible to '[CLPlacemark]' -> swift2

Related

want to query an array from parse that might be empty sometimes but xcode won't let me

func reloadFriendList() {
var query = PFQuery(className:"userFriendClass")
query.whereKey("username", equalTo:user!.username!)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object in objects! {
self.friendList = object["friends"] as! [String]
print(self.friendList)
self.reloadTableView()
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
}
i want to save object["friends"] that is an array from parse with usernames into
var friendList = [String]()
but i get the error: "fatal error: unexpectedly found nil while unwrapping an Optional value",
when the array is empty which means the user doesn't have any friends yet it works fine when the user have at least 1 or more friends.
You need to have your code ready to handle nil cases and cases where "objects" is an empty array.
If this were my code, I would do something like:
for object in objects {
if let friendList = object["friends"]
{
self.friendList = friendList
} else {
// make sure that your class's `friendList` var is declared as an optional
self.friendList = [String]()
}
}
Since objects is optional and may be nil, you need to unwrap it safely. One way to do that is to use the nil coalescing operator to unwrap it or to substitute an empty array if objects is nil. You can use it again to safely unwrap the list of friends:
for object in objects ?? [] {
self.friendList = (object["friends"] as? [String]) ?? []
You can also use optional binding if let to safely unwrap things:
if let unwrappedObjects = objects {
for object in unwrappedObjects {
if let friends = object["friends"] as? [String] {
self.friendsList = friends
} else {
// no friends :-(
self.friendsList = []
}
}
}

Value of type '[NSManagedObject]' can never be nil, comparison isn't allowed

Hi I'm trying to fix SugarRecord a great way to use CoreData and iCloud.
I'm getting this error above with the following method:
public func find(finder: SugarRecordFinder) -> SugarRecordResults
{
let fetchRequest: NSFetchRequest = SugarRecordCDContext.fetchRequest(fromFinder: finder)
var objects = [NSManagedObject]()
do{
objects = try self.contextCD.executeFetchRequest(fetchRequest) as! [NSManagedObject]
}
catch
{
}
if objects == nil {
objects = [NSManagedObject]()
}
return SugarRecordResults(results: SugarRecordArray(array: objects), finder: finder)
}
The error is on the line - if objects == nil {
Though after searching the net I couldn't find a way to fix this. Thank you if you can help.
executeFetchRequest return always an array. If nothing could be found the array is empty.
Just delete
if objects == nil {
objects = [NSManagedObject]()
}
A better syntax is
public func find(finder: SugarRecordFinder) -> SugarRecordResults
{
let fetchRequest: NSFetchRequest = SugarRecordCDContext.fetchRequest(fromFinder: finder)
do {
let objects = try self.contextCD.executeFetchRequest(fetchRequest) as! [NSManagedObject]
return SugarRecordResults(results: SugarRecordArray(array: objects), finder: finder)
}
catch let error as NSError {
// do error handling
return SugarRecordResults()
}
}

Extracting a Parse object of type Bool in xcode7 with swift 2 and using it's value in an if/else statement and get an error

I'm trying to get this Parse object (Boolean) and using it in an if/else statement, but i get an error(on the line with "let basketballOn" line) when i call the object:
Cannot subscript a value of type '[PFObject]?' with an index of type 'String'
var BasketballB = PFObject()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let query = PFQuery(className: "Sports")
query.findObjectsInBackgroundWithBlock { (basketballB:[PFObject]?, error:NSError?) -> Void in
if error == nil {
let basketballON = basketballB["basketballBool"] as Bool
} else {
print(error)
}
}
The query clearly returns an array of PFObject. This means you need to select which object from the array you want before checking the value of any key. To select the first object and test the value of its boolean key you should do something like this:
if let object = basketballB[0] {
let basketballON = object["basketballBool"] as Bool
}

Completion handler giving: Type of expression is ambiguous without more context, after updating to swift 2

I'm using the SODA Client for swift (Created by Socrata), I just updated to XCode 7 and swift 2 and found some troubles. The one I haven't been able to solve is the completion handler case when it finds an error, it's not accepting the line "syncCompletion(.Error (reqError))" that supposedly should get the error and return to main thread.
I've seen many errors with the same description here "Type of expression is ambiguous without more context", but not in completion handlers, I saw one using do - catch that is different. I'm don't know enough of swift to find out the way to change this.
Some answers suppose you should rewrite the code because some types could have change in swift 2, but I wouldn't know where to start rewriting.
Thanks in advance for your help.
var task = session.dataTaskWithRequest(request, completionHandler: { data, response, reqError in
// We sync the callback with the main thread to make UI programming easier
let syncCompletion = { res in NSOperationQueue.mainQueue().addOperationWithBlock { completionHandler (res) } }
// Give up if there was a net error
if reqError != nil {
syncCompletion(.Error (reqError))
return
}
// Try to parse the JSON
// println(NSString (data: data, encoding: NSUTF8StringEncoding))
var jsonError: NSError?
var jsonResult: AnyObject!
do {
jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
} catch var error as NSError {
jsonError = error
jsonResult = nil
} catch {
fatalError()
}
if let error = jsonError {
syncCompletion(.Error (error))
return
}
// Interpret the JSON
if let a = jsonResult as? [[String: AnyObject]] {
syncCompletion(.Dataset (a))
}
else if let d = jsonResult as? [String: AnyObject] {
if let e : AnyObject = d["error"] {
if let m : AnyObject = d["message"] {
syncCompletion(.Error (NSError(domain: "SODA", code: 0, userInfo: ["Error": m])))
return
}
}
syncCompletion(.Dataset ([d]))
}
else {
syncCompletion(.Error (NSError(domain: "SODA", code: 0, userInfo: nil)))
}
})
Solved, I replaced:
if reqError != nil
With
if let error = reqError
and:
syncCompletion(.Error (reqError))
with
syncCompletion(.Error (error))

How to print out value from coredata dictionary in swift 'AnyObject' does not have a member named 'username?

I am trying to print out the value "username" from my coredata entity.
var request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: nil)
if (results?.count > 0) {
for result: AnyObject in results! {
println(result.username)
}
}
The line println(result.username) is giving me a compile error of 'AnyObject' does not have a member named 'username'.
You have to cast the array of managed object to the correct type:
for result in results! as [Users] {
println(result.username)
}
This assumes that you have created a managed object subclass for the "Users" entity.
You should also distinguish whether executeFetchRequest() returned nil
(i.e. the fetch request failed), or 0 (i.e. no objects found),
and use the error parameter:
var error : NSError?
if let results = context.executeFetchRequest(request, error: &error) {
if (results.count > 0) {
for result in results as [Users] {
println(result.username)
}
} else {
println("No Users")
}
} else {
println("Fetch failed: \(error)")
// Handle error ...
}
Update for Swift 2/Xcode 7 with try/catch error handling:
do {
let results = try context.executeFetchRequest(request) as! [Users]
if (results.count > 0) {
for result in results {
print(result.username)
}
} else {
print("No Users")
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
Note that the forced cast as! [Users] is acceptable here.
The returned objects are always instances of the corresponding class as configured in the Core Data model inspector, otherwise you have
a programming error which should be detected early.
Martin's answer definitely lets you access the properties of your object, but the cast is forced. Like it or not, Swift's strong type system is the future. When returning results from a fetch request, you might consider testing for the type.
func executeFetchRequestT<T:AnyObject>(request:NSFetchRequest, managedObjectContext:NSManagedObjectContext, error: NSErrorPointer = nil) -> [T]? {
var localError: NSError? = nil
if let results:[AnyObject] = managedObjectContext.executeFetchRequest(request, error: &localError) {
if results.count > 0 {
if results[0] is T {
let casted:[T] = results as [T]
return .Some(casted)
}
if error != nil {
error.memory = NSError(domain: "error_domain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Object in fetched results is not the expected type."])
}
} else if 0 == results.count {
return [T]() // just return an empty array
}
}
if error != nil && localError != nil {
error.memory = localError!
}
return .None
}
Using this approach you can type your results and get an error if the type is incorrect.
var fetchError:NSError? = nil
if let results:[Users] = executeFetchRequestT(fetchRequest, managedObjectContext: managedObjectContext, error: &fetchError) {
for user in results {
// access the results with confidence of the correct type
}
} else {
// should have an error condition, handle it appropriately
assertFailure("something bad happened")
}
Change your for loop to this
for result: AnyObject in results! {
if let user: AnyObject = result.valueForKey("username") {
println(user)
}
}
The fix is using valueForKey("String")

Resources