During the last months I had the pleasure to do the technical review of a book about DocumentDB written by Riccardo Becker.
It is available at pucktpub now!
https://www.packtpub.com/big-data-and-business-intelligence/learning-azure-documentdb
During the last months I had the pleasure to do the technical review of a book about DocumentDB written by Riccardo Becker.
It is available at pucktpub now!
https://www.packtpub.com/big-data-and-business-intelligence/learning-azure-documentdb
This post is part of my collection: Swift 2 – For Beginners.
Swift extensions add new functionality to an existing class, structure, enumeration, or protocol type.
In this example we will see how to write a UIViewController extension to show loading indicators and alerts.
To add a class extensions we have to write something like:
extension UIViewController { // write your extensions here }
Our first extension method will be a method that should show a loading indicator and disable the application so that the user cannot interact with it. To help the user understand that the application is disabled it should be grayed out.
To use this method we don’t need any parameter but we need a reference to the created indicator to hide it later:
var spinner = self.showModalSpinner()
To do this we can use the class UIActivityIndicatorView.
/** Shows a loading indicator and disables user interaction with the app until it is hidden */ func showModalSpinner() ->UIActivityIndicatorView{ // user cannot interact with the app while the spinner is visible UIApplication.sharedApplication().beginIgnoringInteractionEvents() var indicator = UIActivityIndicatorView() indicator = UIActivityIndicatorView(frame: self.view.frame) indicator.center = self.view.center indicator.backgroundColor = UIColor(white: 0.0, alpha: 0.5) indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray indicator.hidesWhenStopped = true indicator.startAnimating() self.view.addSubview(indicator) return indicator }
Now we need a method to hide the spinner when our task was completed:
self.hideModalSpinner(self.spinnerView)
/** Hides the loading indicator and enables user interaction with the app */ func hideModalSpinner(indicator: UIActivityIndicatorView){ indicator.stopAnimating() indicator.hidden = true // user can interact again with the app UIApplication.sharedApplication().endIgnoringInteractionEvents() }
If we put these two methods within a UIViewController extension we can use them like a normal method of the class.
Let’s add now a method to our extension to show an alert to the user, it should have an ‘ok’ button that will close the alert when the user taps it.
I would like to have a very simple method that has only two parameters to indicate the title and message:
self.showAlert("Error", message: "Invalid user name / password.")
We can use the class UIAlertController to do that:
/** Shows an alert with a title and a message */ func showAlert(title: String, message:String) { let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert) // show the alert with a "ok" button that will close the alert let okAction = UIAlertAction(title: "ok", style: UIAlertActionStyle.Default) { (action) -> Void in self.dismissViewControllerAnimated(true, completion: nil) } alertController.addAction(okAction) // show alert controller self.presentViewController(alertController, animated: true, completion: nil) }
import UIKit extension UIViewController{ /** Shows an alert with a title and a message */ func showAlert(title: String, message:String) { let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert) // show the alert with a "ok" button that will close the alert let okAction = UIAlertAction(title: "ok", style: UIAlertActionStyle.Default) { (action)-> Void in self.dismissViewControllerAnimated(true, completion: nil) } alertController.addAction(okAction) // show alert controller self.presentViewController(alertController, animated: true, completion: nil) } /** Shows a loading indicator and disables user interaction with the app until it is hidden */ func showModalSpinner()->UIActivityIndicatorView{ // user cannot interact with the app while the spinner is visible UIApplication.sharedApplication().beginIgnoringInteractionEvents() var indicator = UIActivityIndicatorView() indicator = UIActivityIndicatorView(frame: self.view.frame) indicator.center = self.view.center indicator.backgroundColor = UIColor(white: 0.0, alpha: 0.5) indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray indicator.hidesWhenStopped = true indicator.startAnimating() self.view.addSubview(indicator) return indicator } /** Hides the loading indicator and enables user interaction with the app */ func hideModalSpinner(indicator: UIActivityIndicatorView){ indicator.stopAnimating() indicator.hidden = true // user can interact again with the app UIApplication.sharedApplication().endIgnoringInteractionEvents() } }
This post is part of my collection: Swift 2 – For Beginners.
In this example we will see how to load photos in our application from the Photo Library and from the camera.
To open the photo library to pickup a photo we need a UIImagePickerController. Our controller can be the delegate. To do that we have to implement the protocols: UINavigationControllerDelegate and UIImagePickerControllerDelegate.
This code creates UIImagePickerController and use the method presentViewController to open the Photo Library:
func selectImage(){ let imagePickerController = UIImagePickerController() imagePickerController.delegate = self imagePickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary imagePickerController.allowsEditing = true self.presentViewController(imagePickerController, animated: true, completion: nil) }
Once the user selects a photo our controller will be called back. Let’s implement a function that will load the selected image into a imageView:
// Pick image finished, show selected image in a imageView func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) { // Show image imageView.image = image self.dismissViewControllerAnimated(true, completion: nil) }
To take a new photo using the camera we just change the value of imagePickerController.sourceType. Instead of PhotoLibrary we use Camera.
We can add a parameter to the previous function to specify the source of our image:
func selectImage(from source: UIImagePickerControllerSourceType){ let imagePickerController = UIImagePickerController() imagePickerController.delegate = self imagePickerController.sourceType = source imagePickerController.allowsEditing = true self.presentViewController(imagePickerController, animated: true, completion: nil) }
import UIKit class ViewController: UIViewController, // 1 Allows navigation to camera or photo library to pick up a photo // used to set this controller as delegate of UIImagePickerController UINavigationControllerDelegate, UIImagePickerControllerDelegate { override func viewDidLoad() { super.viewDidLoad() } @IBOutlet weak var imageView: UIImageView! @IBAction func addFromCamera(sender: AnyObject) { selectImage(from: UIImagePickerControllerSourceType.Camera) } @IBAction func addFromLibrary(sender: AnyObject) { selectImage(from: UIImagePickerControllerSourceType.PhotoLibrary) } // 2 Show image picker or camera app func selectImage(from source: UIImagePickerControllerSourceType){ let imagePickerController = UIImagePickerController() imagePickerController.delegate = self imagePickerController.sourceType = source imagePickerController.allowsEditing = true self.presentViewController(imagePickerController, animated: true, completion: nil) } // 3 Pick image finished, show selected image func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) { // Show image imageView.image = image self.dismissViewControllerAnimated(true, completion: nil) } }
This post is part of my collection: Swift 2 – For Beginners.
JSON (JavaScript Object Notation) is a lightweight, human readable, open source, data-interchange format. In this example we will see how to serialize and deserialize objects to/from JSON using ObjectMapper in our iOS application.
For example, this would be the JSON representation of an object with two properties
name: string = “Juan Carlos”
age: Int = 29
ObjectMapper is an open source project to make JSON Object mapping written in Swift. It is available in github: ObjectMapper.
CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. We will use it to reference ObjectMapper in our project. (If would also be possible to add it as a submodule. Check the project in GitHub for more information)
To add ObjectMapper to our project we need to execute the following commands:
Install cocoapods
sudo gem install cocoapods
Create Podfile in our project root
touch Podfile
To reference ObjectMapper add this content to the PodFile
use_frameworks! pod 'ObjectMapper', '~> 1.0'
Select XCode path
sudo xcode-select --switch /Applications/Xcode.app
Add ObjectMapper repository
pod repo add ObjectMapper https://github.com/Hearst-DD/ObjectMapper.git
Install the project locally
pod install
Close XCode and open the created file *.xcworkspace. It contains our project and a reference to a new project called Pods. All our referenced projects will be contained in this new project.
Now we are ready to import and use ObjectMapper:
import ObjectMapper
To serialize and deserialize objects we must implement the protocol Mappeable.
// Mappeable source code public protocol Mappable { init?(_ map: Map) mutating func mapping(map: Map) }
Let’s write our User class, it will have two properties, name and age. The class will also implement the protocol Mappeable.
// Define our class and implement the Mappable protocol class User: Mappable { var name: String? var age: Int = 0 init(name: String, age: Int) { self.name = name self.age = age } // MARK: Mappable required init?(_ map: Map) { // subClasses must call the constructor of the base class // super.init(map) } func mapping(map: Map) { name <- map["name"] age <- map["age"] } }
ObjectMapper is extremely easy to use:
// Object to be serialized to JSON let myUser = User(name: "Juan Carlos", age: 29) // Convert Object to JSON let serializedUser = Mapper().toJSONString(myUser) print(serializedUser) // Convert JSON to Object if let deserializedUser = Mapper<User>().map(serializedUser){ print(deserializedUser.name) } // Output: // Optional("{\"age\":29,\"name\":\"Juan Carlos\"}") // Optional("Juan Carlos")
This post is part of my collection: Swift 2 – For Beginners.
Core Data is a persistence framework provided by Apple. In this example we will see how to use it in our iOS application. First we will see how to create our data model and then how to perform the following basic operations:
A data model consist of a group of entities. The concept of entity in Core Data is similar to the concept of table in SQL. Each entity can have attributes in the same way that a table can have columns.
To create a new entity you need a project with Core Data included. Then go to your xdatamodel file and click “Add Entity”, “Add Attribute” to configure it.
To keep the example simple our data model will have one entity with two attributes. A Person with name and age:
Person
-name: string
-age: integer
To create a class that represent our data model click on “Editor” > “Create NSManagedObject Subclass…”.
It should create a class and an extension representing our entity “Person”. To that class we will only add a static field with the entity name, we will use it later to avoid magic strings:
extension Person { @NSManaged var name: String? @NSManaged var age: NSNumber? }
class Person: NSManagedObject { // Add this line, the string must be equal to your class name static let entityName = "Person" }
Before writing code to make our basic operations it is important to know what the managedObjectContext is.
When the project has Core Data Xcode add a bunch of code to our AppDelegate.swift. A piece of that code is the managedObjectContext. This is the object that we need to access the data model. We can get it in our controller with this line of code:
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
To save our changes we always have to call context.save(). It can throw an exception so we have to make the call in a do.. catch.. block:
// Saves all changes func saveChanges(){ do{ try context.save() } catch let error as NSError { // failure print(error) } }
Now we are ready to write our basic functions to access the data model:
// Creates a new Person func create(name: String, age: NSNumber) -> Person { let newItem = NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as! Person newItem.name = name newItem.age = age return newItem }
// Gets a person by id func getById(id: NSManagedObjectID) -> Person? { return context.objectWithID(id) as? Person }
Now we will see how to get all entities and how to get all entities applying a NSPredicate to our query.
// Gets all with an specified predicate. // Predicates examples: // - NSPredicate(format: "name == %@", "Juan Carlos") // - NSPredicate(format: "name contains %@", "Juan") func get(withPredicate queryPredicate: NSPredicate) -> [Person]{ let fetchRequest = NSFetchRequest(entityName: Person.entityName) fetchRequest.predicate = queryPredicate do { let response = try context.executeFetchRequest(fetchRequest) return response as! [Person] } catch let error as NSError { // failure print(error) return [Person]() } }
Our get all function will be a call to the previous function. The predicate will be a true predicate, to return all objects in our data model.
// Gets all. func getAll() -> [Person]{ return get(withPredicate: NSPredicate(value:true)) }
// Updates a person func update(updatedPerson: Person){ if let person = getById(updatedPerson.objectID){ person.name = updatedPerson.name person.age = updatedPerson.age } }
// Deletes a person func delete(id: NSManagedObjectID){ if let personToDelete = getById(id){ context.deleteObject(personToDelete) } }
This class puts all the functions that we have seen before together, we can call it PersonService.
import CoreData class PersonService{ var context: NSManagedObjectContext init(context: NSManagedObjectContext){ self.context = context } // Creates a new Person func create(name: String, age: NSNumber) -> Person { let newItem = NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as! Person newItem.name = name newItem.age = age return newItem } // Gets a person by id func getById(id: NSManagedObjectID) -> Person? { return context.objectWithID(id) as? Person } // Gets all. func getAll() -> [Person]{ return get(withPredicate: NSPredicate(value:true)) } // Gets all that fulfill the specified predicate. // Predicates examples: // - NSPredicate(format: "name == %@", "Juan Carlos") // - NSPredicate(format: "name contains %@", "Juan") func get(withPredicate queryPredicate: NSPredicate) -> [Person]{ let fetchRequest = NSFetchRequest(entityName: Person.entityName) fetchRequest.predicate = queryPredicate do { let response = try context.executeFetchRequest(fetchRequest) return response as! [Person] } catch let error as NSError { // failure print(error) return [Person]() } } // Updates a person func update(updatedPerson: Person){ if let person = getById(updatedPerson.objectID){ person.name = updatedPerson.name person.age = updatedPerson.age } } // Deletes a person func delete(id: NSManagedObjectID){ if let personToDelete = getById(id){ context.deleteObject(personToDelete) } } // Saves all changes func saveChanges(){ do{ try context.save() } catch let error as NSError { // failure print(error) } } }
How to use the service:
// Create an instance of the service. let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext let personService = PersonService(context: context) // Create let juanCarlos = personService.create("Juan Carlos", age: 52) // Read all var people : [Person] = personService.getAll() // Read by id let firstPerson = personService.getById(people[0].objectID)! // Update firstPerson.name = "Juan Carlos Sanchez" personService.update(firstPerson) // Delete personService.delete(firstPerson.objectID)