You have found PodioPlatformKit, the official Objective-C and Swift SDK for Podio Platform. It works with both iOS and Mac OS X.

Build Status

For help post on Stack Overflow and tag with podio. For bugs create an issue on GitHub.

Basic Principles of Asynchronicity

PodioPlatformKit’s main responsibility os making request to the Podio API. To do so, it needs to provide a mean of handling asynchronous method calls. PodioPlatformKit uses a future-based approach where each asynchronous method returns an instance of PKTAsyncTask. You can then register callbacks (onSuccess(_), onError(_) and onComplete(_)) on this tasks that will be called according to the following rules:

To register a callback, you have three options:

The onSuccess(_) method is used to register callbacks to be executed if the task succeeds, meaning it does not generate an error:

let task = SomeClass.someAsynchronousMethod()

task.onSuccess { (response: PKTResponse!) in
  // The task finished successfully
}

The onError(_) method can be used to register callbacks for the error case:

let task = SomeClass.someAsynchronousMethod()

task.onSuccess { (error: NSError?) in
  // The task failed and returned an error
}

If you are interested in both the success and error case at the same time, you can use the onComplete(_) method to register a callback for when either happens:

let task = SomeClass.someAsynchronousMethod()

task.onComplete { (response: PKTResponse?, error: NSError?) in
  if let error = error {
    // Task failed
  } else {
    // Task succeeded
  }
}];

The main advantage of modelling asynchronisity with futures is that you can chain tasks together to acheive some things. PodioPlatformKit provides a few combinator methods to combine sub-tasks in to bigger tasks. Consider for example if you first want to upload a task, then attach it to an object. With a callback approach you would have to nest your callback handlers:

let data: NSData = ...; // Some image data

PKTFile.uploadWithData(data, fileName:@"image.jpg", completion: { (file: PKTFile?, error: NSError?) in
  if let file = file {
    file.attachWithReferenceID(1234, referenceType: .Item completion: { (response: PKTResponse?, error: NSError?) in 
      if error == nil {
        // Handle success
      } else {
        // Handle failure
      }
    })
  } else {
    // Handle failure
  }
})

You can see that we have to handle the error case twice. With a task based approach, we can instead use the pipe(_) combinator method which takes a block that generates a new task based on the result of the first task once completed:

let data: NSData = ...; // Some image data

let task = PKTFile.uploadWithData(data, fileName:@"image.jpg")
  .pipe { (file: PKTFile?) in
    return file.attachWithReferenceID(1234, referenceType: .Item)
}

task.onComplete { (response: PKTResponse?, error: NSError?) in
  if let error = error {
    // Handle failure
  } else {
    // Handle success
  }
}];

Here, we only have to handle the error case once and we do not end up with deeply nested code blocks. There are also other useful combinator methods such as when(_), then(_) and map(_) available.