Upload and retrieve photos using Amazon iOS SDK and Swift – Part 2

In the first part of the simple iOS mobile app (toDoList) tutorial series, you covered the basics of setting environment, user interface/autolayout and AWS setting.

In this second and final part of the tutorial series, we’ll cover AWS integration.

We’ll start where we left off last tutorial, so open your project from last time, or go through the previous tutorial first. http://blog.revivalx.com/2015/09/30/upload-and-retrieve-photos-using-amazon-ios-sdk-and-swift-part-1/

Upload and retrieve photos using Amazon iOS SDK and Swift – Part 1

Here a cool tutorial how to upload and retrieve photos using Amazon iOS SDK and Swift. You can learn the foundation here, https://aws.amazon.com/mobile/sdk/.

Amazon Web Services.

Amazon Web Services.

Getting Started.

Before we start the tutorial, I assumed you already registered your account in AWS. Then setup Amazon Cognito and S3 here

Open your Xcode 7.1. Open Xcode and create a new Single View Application. For product name, use RevivalxSwiftAmazonS3 and then fill out the Organization Name and Organization Identifier with your customary values. Enter Swift as Language and make sure only iPhone is selected in Devices.

Single View Application

Single View Application

RevivalxSwiftAmazonS3

RevivalxSwiftAmazonS3

Install CocoaPods in your machine. Follow this tutorial for more details, http://blog.revivalx.com/2015/06/25/using-3rd-party-libraries-using-cocoapods/. Before you execute pod install command, replace with this code and run pod install command.

# Uncomment this line to define a global platform for your project
# platform :ios, '6.0'
use_frameworks!

pod 'Alamofire', '~> 1.2'
pod 'HanekeSwift'
pod 'SwiftyJSON', '~> 2.2.0'
pod 'AWSS3'

target 'RevivalxSwiftAmazonS3' do

end

target 'RevivalxSwiftAmazonS3Tests' do

end
CocoaPods - pod install

CocoaPods – pod install

Go to Main.Storyboard and set to Compact Width | Any Height.

Compact Width | Any Height

Compact Width | Any Height

Go to UIViewController in Main.Storyboard and remove UIView. Then go to Show the Object Library and add UICollectionView in UIViewController.

 

UIViewController - Remove UIView

UIViewController – Remove UIView

 

UIViewController - Add UICollectionView

UIViewController – Add UICollectionView

Hold control button and drag from UICollectionView to yellow square icon like image below. Make sure you select both dataSource and delegate.

 

UIViewController - DataSource and delegate outlet.

UIViewController – DataSource and delegate outlet.

Select the Table View Controller again and in the menu go to Editor > Embed In >Navigation Controller. This adds a Navigation Controller to the storyboard with an initial scene.

Editor > Embed In > Navigation Controller

Editor > Embed In > Navigation Controller

Select RevivalxSwiftAmazonS3. Go to File > New > File… to create a new file. Select Cocoa Touch Class under iOS > Source and click Next.

Choose a template for your new file

Choose a template for your new file

Select UICollectionViewCell from Subclass of. Click Next and Create after you select file directory to save.

UICollectionViewCell

UICollectionViewCell

Select one more time on RevivalxSwiftAmazonS3 group. Go to File > New > File… to create a new file. This time we need to create a bridging header file to user Amazon SDK. Select Objective-C File under iOS > Source and click Next.

Objective-C File

Objective-C File

Name it CustomObject. Click Next and Create.

xcode6 - new file

xcode6 – new file

When adding your .m file, you’ll likely be hit with a prompt that looks like this below and click Yes.

Objective-C bridging header

Objective-C bridging header

Your CustomObject.m and SimpleiOSApp-Bridging-Header.h have been created. Add another .h file and name it CustomObject.hFile > New > File. Select iOS >Source > Header File. Click Next . Name it CustomObject and click Create.

Header File

Header File

Now add Class to Bridging-Header. In YourProject-Bridging-Header.h (For this tutorial is RevivalxSwiftAmazonS3-Bridging-Header.h):

#import <AWSS3/AWSS3.h>;

Copy Cognito Identity Pool Id from Amazon Cognito. Make sure you know region type for Amazon Cognito and S3. Open AppDelegate.swift and update the with this code.

import UIKit
import AWSS3

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var cognitoIdentityPoolId: String = "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -&gt; Bool {
        let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.APNortheast1, identityPoolId: cognitoIdentityPoolId)
        
        let defaultServiceConfiguration = AWSServiceConfiguration(
            region: AWSRegionType.APSoutheast1, credentialsProvider: credentialsProvider)
        
        AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration
        
        return true
    }

    func applicationWillResignActive(application: UIApplication) {
    }

    func applicationDidEnterBackground(application: UIApplication) {
    }

    func applicationWillEnterForeground(application: UIApplication) {
    }

    func applicationDidBecomeActive(application: UIApplication) {
    }

    func applicationWillTerminate(application: UIApplication) {
    }
}

Continue..

iOS Swift Basics Tutorial: Protocols and Delegates

Here a cool tutorial protocols and delegates using Swift. This link will explain more details about the delegate, https://www.andrewcbancroft.com/2015/03/26/what-is-delegation-a-swift-developers-guide/.

Getting started.

Before we start this tutorial, make sure you already setup your machine (mac) with these tools:

  1. Xcode 7.1: https://developer.apple.com/xcode/

Open Xcode and create a new Single View Application. For product name, use RevivalxSwiftProtocolDelegate and then fill out the Organization Name and Organization Identifier with your customary values. Enter Swift as Language and make sure only iPhone is selected in Devices.

Single View Application

Single View Application

RevivalxSwiftProtocolDelegate

RevivalxSwiftProtocolDelegate

Go to Main.Storyboard and set to Compact Width | Any Height.

Compact Width | Any Height

Compact Width | Any Height

Select View Controller in storyboard and select Editor > Embed In > Navigation Controller.

Embed in Navigation Controller.

Embed in Navigation Controller.

Navigation Controller.

Navigation Controller.

Go to Object Library and drag/drop a new View Controller into storyboard.

Main.Storyboard.

Main.Storyboard.

Go to Object Library again and drag/drop Bar Button Item into first view controller. Change the Bar Button Item icon to plus icon. Then press control button and at the same time drag the mouse/pointer to second view controller. Select show under Action Segue. Finally add Navigation Item into second view controller and name it for both view controllers.

Main.Storyboard.

Main.Storyboard.

Drag and drop Label and TextField from Object Library into both view controllers. Make sure it similar with example below. Don’t forget to set autolayout for each label and textfield. If you not really understand about the autolayout, feel free to read this tutorial. http://www.raywenderlich.com/83129/beginning-auto-layout-tutorial-swift-part-1

Main.Storyboard.

Main.Storyboard.

Create a new ViewController.swift (UIViewController).

Xcode 6.4 – New File.

Xcode 6.4 – New File.

Cocoa Touch Class

Cocoa Touch Class

UIViewController

UIViewController

Project navigator.

Project navigator.

Select second view controller and make sure you attach SecondViewController into each controllers in Identity inspector.

Identity inspector -UIViewController

Identity inspector -UIViewController

Select the Assistant Editor and open SecondViewController.swift. Ctrl and drag from the Text Field to the ViewController class to create the following outlet.

TextField outlet.

TextField outlet.

Ctrl and drag from the Button and create the following action.

Button outlet.

Button outlet.

Open ViewController.swift. Ctrl and drag from the Label to the ViewController class to create the following outlet.

Label outlet.

Label outlet.

Select Attribute inspector and name it as SecondSegue in Identifier field.

Storyboard segue.

Storyboard segue.

Go to the SecondViewController.swift file and replace with this code.

import UIKit

protocol DataEnteredDelegate{
    func userDidEnterInformation(info: NSString)
}

class SecondViewController: UIViewController {

    @IBOutlet weak var txtData: UITextField!
    var delegate:DataEnteredDelegate? = nil
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    @IBAction func sendData(sender: AnyObject) {
        if (delegate != nil){
            let data: NSString = txtData.text
            
            delegate!.userDidEnterInformation(data)
            self.navigationController?.popViewControllerAnimated(true)
        }
    }
}

Open ViewController.swift and update the with this code.

import UIKit

class ViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var lblResult: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    func userDidEnterInformation(info: NSString) {
        lblResult.text = info as String
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == &quot;SecondSegue&quot; {
            let secondViewController: SecondViewController = segue.destinationViewController as! SecondViewController
            secondViewController.delegate = self
        }
    }
}

Run your project. Feel free to check out my source code here, https://github.com/datomnurdin/RevivalxSwiftProtocolDelegate.

Develop a simple iOS mobile app (toDoList) using Swift – Part 2

In the first part of the simple iOS mobile app (toDoList) tutorial series, you covered the basics of setting environment and user interface/autolayout.

In this second and final part of the tutorial series, we’ll cover Parse integration.

We’ll start where we left off last tutorial, so open your project from last time, or go through the previous tutorial first. http://blog.revivalx.com/2015/05/13/develop-a-simple-ios-mobile-app-todolist-using-swift-part-1/

Select UITableViewController in Main.Storyboard and edit Attribute Inspector according to this setting:

Style: Basic
Identifier: TaskCell
Accessory: Disclosure Indicator

Attribute Inspector.

Attribute Inspector.

UiTableViewController

UiTableViewController

Go to UIViewController and make sure the user interface is similar like this one. Don’t forget to set constraints for each elements. If you don’t know how to do it, feel free to refer it here, https://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOS/DesigningaUserInterface.html.

UIViewController.

UIViewController.

Sign up for your new account here, https://www.parse.com/.

Parse

Parse

Click Create a New App.

Create a New App

Create a New App

Go to Keys and save your Application ID and Client Key. Open AppDelegate.swift file and update the Application ID and Client Key.

import UIKit
import ParseFacebookUtils
 
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
 
  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -&gt; Bool {
    // [Optional] Power your app with Local Datastore. For more info, go to
    // https://parse.com/docs/ios_guide#localdatastore/iOS
    Parse.enableLocalDatastore()
 
    // Initialize Parse.
    Parse.setApplicationId(&quot;xxxxx&quot;,
      clientKey: &quot;xxxxx&quot;)
 
    // [Optional] Track statistics around application opens.
    PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
 
    // ...
}
 
// ...

Create two Cocoa Touch Class. One is TableViewController.swift (UITableViewController) and the other one is ViewController.swift (UIViewController).

Xcode 6.4 - New File.

Xcode 6.4 – New File.

Cocoa Touch Class

Cocoa Touch Class

UITableViewController

UITableViewController

UIViewController

UIViewController

Project navigator

Project navigator

Then make sure you attach both files into each controllers in Identity inspector.

Identity inspector - UITableViewController

Identity inspector – UITableViewController

Identity inspector -UIViewController

Identity inspector -UIViewController

Select Table View Cell, go to Identity Inspector and select PFTableViewCell.

PFTableViewCell

PFTableViewCell

Create Task model.

Swift File.

Swift File.

Project navigator

Project navigator

Go to the Task.swift file and replace with this code.

import Foundation
import UIKit

class Task: NSObject {
    var taskId: Int
    var name: String
    
    init(taskId: Int, name: String) {
        self.taskId = taskId
        self.name = name
        super.init()
    }
}

Open TableViewController.swift and update the with this code.

import UIKit
import Parse
import ParseUI

class TableViewController: PFQueryTableViewController {
    
    var id: String!
    var name: String!
    var descriptions: String!
    
    override init(style: UITableViewStyle, className: String?) {
        super.init(style: style, className: className)
    }
    
    @IBAction func addNewTask(sender: AnyObject) {
        self.id = nil
        self.performSegueWithIdentifier("MySegue", sender: self)
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        self.parseClassName = "Task"
        self.textKey = "name"
        self.pullToRefreshEnabled = true
        self.paginationEnabled = false
        
    }
    
    override func queryForTable() -> PFQuery {
        var query = PFQuery(className: "Task")
        query.orderByAscending("name")
        
        
        return query
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.tableView.estimatedRowHeight = 44
        self.tableView.rowHeight = UITableViewAutomaticDimension
        self.tableView.reloadData()
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
        var cell = tableView.dequeueReusableCellWithIdentifier("TaskCell") as! PFTableViewCell!
        if cell == nil {
            cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
        }
        
        cell.textLabel?.text = object!["name"] as? String
        
        return cell
    }

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            let objectToDelete = objects?[indexPath.row] as! PFObject
            objectToDelete.deleteInBackgroundWithBlock {
                (success: Bool, error: NSError?) -> Void in
                if (success) {
                    self.tableView.reloadData()
                }
            }
        }
    }
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let object = objects?[indexPath.row] as! PFObject
        var query = PFQuery(className:"Task")
        query.getObjectInBackgroundWithId(object.objectId!) {
            (task: PFObject?, error: NSError?) -> Void in
            if error == nil && task != nil {
                self.id = task!.objectId!
                self.name = task!["name"] as! String
                self.descriptions = task!["description"] as! String
                self.performSegueWithIdentifier("MySegue", sender: self)
            } else {
                print(error)
            }
        }
    }
    
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "MySegue" {
            let viewController: ViewController = segue.destinationViewController as! ViewController
            viewController.id = id
            viewController.name = name
            viewController.descriptions = descriptions
        }
    }
}

Open ViewController.swift and replace the with this code.

import UIKit
import Parse

class ViewController: UIViewController {

    @IBOutlet weak var txtName: UITextField!
    @IBOutlet weak var txtDescription: UITextField!
    var id: String!
    var name: String!
    var descriptions: String!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        if id != nil {
            txtName.text = name
            txtDescription.text = descriptions
        }
    }

    @IBAction func btnSubmit(sender: AnyObject) {
        if id != nil {
            var query = PFQuery(className:"Task")
            query.getObjectInBackgroundWithId(id) {
                (task: PFObject?, error: NSError?) -> Void in
                if error != nil {
                    print(error)
                } else if let task = task {
                    task["name"] = self.txtName.text
                    task["description"] = self.txtDescription.text
                    task.saveInBackground()
                    self.navigationController!.popViewControllerAnimated(true)
                }
            }
        } else {
            var task = PFObject(className:"Task")
            task["name"] = txtName.text
            task["description"] = txtDescription.text
            task.saveEventually()
            navigationController!.popViewControllerAnimated(true)
        }
    }
}

Result

ToDoList Screenshot 1

ToDoList Screenshot 1

 

ToDoList Screenshot 2

ToDoList Screenshot 2