The significance of the Bool value of PFUser signUpInBackgroundWithBlock - ios

I am wondering what is the significance of the succeeded Bool value in the function block? As I have seen sample codes from parse ignores it and only check if error is nil or not.
If the bool value is not required, why is it there in the first place?
user.signUpInBackgroundWithBlock({ (succeeded: Bool, error: NSError?) -> Void in
if error == nil {
if succeeded { // IS THIS REQUIRED AT ALL??
}
}
else {
}
});
Or we could just do this?
user.signUpInBackgroundWithBlock({ (succeeded: Bool, error: NSError?) -> Void in
if error == nil {
//Do something
}
else {
}
});

Related

Getting Error with PFAnonymousUtils.logIn

The Code below returns an error:
Cannot Covert value of type '(PDUser!, NSError!) -> Void' to expected argument type 'PFUserResultBlock'
PFAnonymousUtils.logIn{ (user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user != nil {
println("Success")
}
} else {
println("Failed")
}
}
I looked at a few examples below for reference to see if there was a solution:
(1)Parse Facebook logInInBackgroundWithReadPermissions
(2)PFFacebookUtils login background cannot convert value to PFUserResultBlock
(3) iOS Developers Guide
The type inference is being thrown off. Try without the types. So PFAnonymousUtils.logIn{ (user, error) in This might fix it.
So With some help here's a complete solution:
Taking a suggestion where I would have to place :
PFAnonymousUtils.logIn{ (user, error) in
over
PFAnonymousUtils.logIn{ (user: PFUser?, error: NSError?) -> Void
the next error would be this line:
if let user = user {
where the compiler assumes that this isn't an optional, so the final solution in code would be
PFAnonymousUtils.logIn{ (user, error) in
if error == nil {
print("Success")
}
else {
print("Failed")
}
}
This way, it checks for an error, if there is an error, the code will print a line indicating as such.

Parse SDK methods not working in Xcode 6.3 Beta

So far I am having issues with blocks like this:
user.signUpInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
if error == nil {
println("success")
} else {
println("\(error)");
// Show the errorString somewhere and let the user try again.
}
}
When I add this into Xcode I get this:
Cannot invoke 'signUpInBackgroundWithBlock' with an argument list of type '((Bool!, NSError!) -> Void)'
When I run this code in Xcode 6.3 (non beta) it works fine. But in the Beta it fails and wont allow me to build. Any ideas if this will be cleared up or if there is a different implementation that I could use. Ive tried using just the signUpInBackgroundWithTarget but Im just not able to access the error correctly if one is received.
be sure you are using SDK version 1.7.1, then removing the types from your closure should do the trick:
user.signUpInBackgroundWithBlock { (succeeded, error) -> Void in
if error == nil {
println("success")
} else {
println("\(error)");
// Show the errorString somewhere and let the user try again.
}
}
Due to the new addition of "Nullability Annotations" to Swift 1.2, you have to rewrite the code above like this (using Parse 1.7.1+):
user.signUpInBackgroundWithBlock { (succeeded: Bool, error: NSError?) -> Void in
if let error = error {
println(error) // there is an error, print it
} else {
if succeeded {
println("success")
} else {
println("failed")
}
}
}
Parse is now returning optionals (?) instead of explicitely unwrapped objects (!).
Notation of Swift is changed
class AAPLList : NSObject, NSCoding, NSCopying {
// ...
func itemWithName(name: String!) -> AAPLListItem!
func indexOfItem(item: AAPLListItem!) -> Int
#NSCopying var name: String! { get set }
#NSCopying var allItems: [AnyObject]! { get }
// ...
}
After annotations:
class AAPLList : NSObject, NSCoding, NSCopying {
// ...
func itemWithName(name: String) -> AAPLListItem?
func indexOfItem(item: AAPLListItem) -> Int
#NSCopying var name: String? { get set }
#NSCopying var allItems: [AnyObject] { get }
// ...
}
So you can change
(succeeded: Bool!, error: NSError!) -> Void in
to
(success: Bool, error: NSError?) -> Void in
Which Parse SDK are you using? They released version 1.7.1 a few days ago that should fix your issue.
Change:
(succeeded: Bool!, error: NSError!) -> Void in
to
(succeeded, error) -> Void in
This change is required due to changes in the Parse SDK

Cannot reference a local function with capture from another local function (swift)

var first_name = ""
func problemFunc() {
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
first_name = fbGraphUserDict["first_name"] as NSString
println(first_name)
}
}
}
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc() // error is here
}
})
This code is inside an #Ibaction button. I cannot build because the call to problemFunc() triggers the error message in the title of this post. If I move the first_name var definition inside the problemFunc it will work ok. But I need it out, because another function will need to access its value.
I'm really not sure at what causes this problem, if you have a clue, please help.
Use a closure instead of a function:
var first_name = ""
let problemFunc = { () -> () in
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
first_name = fbGraphUserDict["first_name"] as NSString
println(first_name)
}
}
}
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc() // error is here
}
})
Here are the basic principles in play: (from Apple's docs: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID103)
"Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:
Global functions are closures that have a name and do not capture any values.
Nested functions are closures that have a name and can capture values from their enclosing function.
Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context."
ie this is ok
func someFunc() {
func nestFunc() {}
}
but this is not
func someFunc() {
func nestFunc() {
func nestedFunc2() { }
}
}
If you look at this in Xcode the third function (func nestedFunc2) will give you the error "Cannot reference a local function with capture from another local function"
The top function (func someFunc) is a global scope function and those work like regular functions/methods.
The second function (func nestFunc) is a nested function which is a named closure one level deep that can capture the scope of its parent global function.
Nested functions, can capture the scope of a global function but not the scope of another nested function.
That's why we need a closure i.e.
func someFunc() {
func nestFunc() {
let strictClosure = { () -> () in
//this is where you write the code
}
}
}
#fluidsonic answer should solve the problem. However note that you're doing some spaghetti code, because you are modifying a variable captured by a closure, and executed in the context of another function. That's hard to track if you need to debug, and more generally hard to follow when and how that variable is modified.
A more linear and better readable flow is to define problemFunc as a function taking a function as parameter, and calling that function rather than directly setting the value in the first_name variable:
let problemFunc = { (callback: (String -> Void) -> ()) in
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
let first_name = fbGraphUserDict["first_name"] as NSString
callback(first_name) // << here you call the callback passing the `first_name` local variable
println(first_name)
}
}
}
and do the actual assignment to first_name in a closure you define when calling problemFunc:
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc { (name: String) -> Void in
first_name = name
}
}
})

How do I use a completionBlock in swift?

I'm trying to utilize swift's SKStoreProductViewController, but am getting errors with my syntax, specifically with my completion block.
Here is my code:
let storeViewController:SKStoreProductViewController = SKStoreProductViewController();
storeViewController.delegate = self;
var productparameters = [SKStoreProductParameterITunesItemIdentifier:someitunesid];
storeViewController.loadProductWithParameters(productparameters,
(success: Bool!, error: NSError!) -> Void in
if success {
self.presentViewController(storeViewController, animated: true, completion: nil);
} else {
NSLog("%#", error)
}
)
After running this I get an expected "," separator error between the error:NSError!),-> Void
This doesn't make sense to me as the apple docs call for:
func loadProductWithParameters(_ parameters: [NSObject : AnyObject]!,
completionBlock block: ((Bool, NSError!) -> Void)!)
What am I doing wrong?
You're 99% there, you just need braces around your block to have the correct closure syntax:
storeViewController.loadProductWithParameters(productparameters, { (success: Bool!, error: NSError!) -> Void in
if success {
self.presentViewController(storeViewController, animated: true, completion: nil);
} else {
NSLog("%#", error)
}
})
You can read more about closures in Apple's documentation.

Parse Objective - C to Swift iOS

I am having trouble trying to change Objective - C code to Swift. This is with the Parse framework. If anyone knows how the following code should be written in Swift, it would help me a lot.
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
//The registration was successful, go to the wall
[self performSegueWithIdentifier:#"SignupSuccesful" sender:self];
}
[NSObject: Anyobject]? does not have a member named subscript parse compile error will be thrown.
The code should be like that because userInfor maybe be nil.
user.signUpInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
if !(error != nil) {
// Hooray! Let them use the app now.
} else {
if let errorString = error.userInfo?["error"] as? NSString {
println(errorString)
}
}
}
Parse happens to have an example of this exact method in their documentation. I think they'll be OK if I excerpt it here:
user.signUpInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
if !error {
// Hooray! Let them use the app now.
} else {
let errorString = error.userInfo["error"] as NSString
// Show the errorString somewhere and let the user try again.
}
}
It would be something like this.
user.signUpInBackground {
(success: Bool!, error: NSError!) -> Void in
if !error {
[unowned self] in
self.performSegue("SignupSuccesful", sender:self);
}
Edit: Parse actually has Swift support. Here's a tutorial for it.
Edit2: You shouldn't refer to self inside a block. Use unowned self instead.

Resources