Shrikar Archak

It does not matter how slow you go so long as you do not stop. ~Confucius

iOS 8 Custom Transitions in Swift

iOS provides a few transitions like Modal, Push and a few more. But if you want to make your app looks different and want to have light weight transitions within your app then you are in for a treat with Custom transitions.

Lets try to implement the same in our How to make a photography inspiration appand Part 2 Swift iOS Tutorial: Taming UITableView Visual Blur and Autolayout.

images

There are a few things which we need to make custom transitions work.

Our view controller which will begin the transition should implement the UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning

Lets create a DetailViewController which has an imageview within that and setup the autolayout constraints with value 0 to superview on all the sides. If we want to go to a detailViewController on selecting a tableView cell we could implement our tableView didSelectRowAtIndexPath as below

didSelectRowAtIndexPath
1
2
3
4
5
6
7
8
9
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let dvc = DetailViewController(nibName: "DetailViewController", bundle: nil)
    dvc.photo = self.photos[indexPath.row]
    dvc.transitioningDelegate = self
    dvc.modalPresentationStyle = UIModalPresentationStyle.Custom
    let currRect = self.tableView.rectForRowAtIndexPath(indexPath)
    self.point = CGPointMake(currRect.midX, currRect.midY)
    self.presentViewController(dvc, animated: true, completion: nil)
}

The key thing to note here are the setting up of transitioningDelegate to self and the modalPresentationStyle to UIModalPresentationStyle.Custom. Once we have set this up we can present the view controller.

Next we need to implement the functions which will perform the actual transitions.

AnimationControllers
1
2
3
4
5
6
7
8
9
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    isPresenting = true
    return self
}

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    isPresenting = false;
    return self
}

Swift iOS Tutorial: Taming UITableView Visual Blur and Autolayout

This is the part 2 of Building a Photography inspiration app if you haven’t looked at the part 1 I strongly suggest you to complete that part before continuing.

In the previous post we have successfully converted the json into a domain specific model like Photo. Instead of dealing with json directly we will be using the photo model in our view controllers.

UITableView is one of the versatile class which can be used in many different usecases. We will be using UITableView to display a list of Photos in our application along with the exif data associated with the Photo.

Lets get started with our app in Xcode 6.

  • Delete the existing viewcontroller on the mainstory board and drag a uitableview controller from the object library on to the mainstory board. images
  • Create a PhotoListController class which is a subclass of UITableViewController.
  • Create a PhotoCell class which will be a subclass of UITableViewCell.
  • Select the PhotoListController and in the identity inspector set the class as PhotoListController. images
  • Similarly select the PhotoCell and set the class as PhotoCell.
  • Next step is customizing the PhotoCell.
    • Drag a imageview
    • Drag a visual blur view on top of imageview at the bottom.
    • Drag multiple uilable for each of the camera, iso, shutterspeed etc.
    • Select the element and arrange them approximately how you want them to be laid out.

Swift iOS Tutorial: Building a Photography Inspiration App - Part 1

If you have been following my blog posts you may know that we are going to build an app every month to learn new iOS concepts. You can find previous tutorial here How to make an app.

This month we will be learning how to build a photography inspiration app. This app will help you learn / get new tricks by looking at the photos, the place where they took it and what kind of setting they used to get that photograph along with details like the camera used, lens used, shutter speed , aperture and more.

If you have some more awesome ideas/feature for this app. Please comment below.

Here are a few things which we will learn in this app.

  • ) How to make an app interact with REST api’s.
  • ) Designing models in Swift.
  • ) More about UITableView and UICollectionview customization
  • ) Animations.

We will be using 500px data to search for certain keywords. To do that lets go ahead and create an app on 500px Developer page. Once you have the token you can test out certain sample REST api’s.

Example : If you want to search for photos in the landscape category and sort it by the highest rating and provide high res images with 100 photos per query we can perform a query like below.

REST API
1
https://api.500px.com/v1/photos/search?only=Landscapes&image_size=4&sort=highest_rating&rpp=100&consumer_key=you api key

You can run the query and find out what kind of data is returned.

Create a single view application and in the main storyboard select the view controller and set the view controller class to ViewController in the identity inspector.

At this point we will get into the model design.

In our application we will deal with one main model object which will be our Photo Model.

Photo.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Photo: NSObject {

    var name: String?
    var info: String?
    var camera: String?
    var lens: String?
    var focalLength: String?
    var iso: String?
    var shutterSpeed: String?
    var highest_rating: Double?
    var imageurl: String?
    init(data: JSON) {
        self.name = data["name"].stringValue
        self.info = data["description"].stringValue
        self.camera = data["camera"].stringValue
        self.lens = data["lens"].stringValue
        self.focalLength = data["focal_length"].stringValue
        self.iso = data["iso"].stringValue
        self.shutterSpeed = data["shutter_speed"].stringValue
        self.highest_rating = data["highest_rating"].doubleValue
        self.imageurl = data["images"][0]["url"].stringValue
    }
}

Swift iOS Tutorial: UISearchBar and UISearchBarDelegate

One of the important feature in an iOS application would be searching functionality, today we will be learning how to add search to our tableview application in Swift.

UISearchBar

The UISearchBar class implements a text field control for text-based searches. The control provides a text field for entering text, a search button, a bookmark button, and a cancel button. The UISearchBar object does not actually perform any searches. You use a delegate, an object conforming to the UISearchBarDelegate protocol, to implement the actions when text is entered and buttons are clicked. You can hide and show the cancel button by setting showsCancelButton to false or true.

UISearchBarDelegate

The UISearchBarDelegate protocol defines the optional methods you implement to make a UISearchBar control functional. A UISearchBar object provides the user interface for a search field on a bar, but it’s the application’s responsibility to implement the actions when buttons are tapped. At a minimum, the delegate needs to perform the actual search when text is entered in the text field.

The main function which we will be implementing are

delegate
1
2
optional func searchBar(_ searchBar: UISearchBar,
          textDidChange searchText: String)

We will maintain a boolean variable searchActive to decide if the search is in progress.

Steps to implement search

  • Create a single view application. images

  • Disable Size classes for now. images

  • Select the tableview and set the autolayout constraints to 0. images

If you are interested in learning iOS Development I suggest you take a look at Building an app every month in 2015

Core Data Stack: Save and Fetch Entities

In the previous post we saw how to build a simple Core Data application. Also if you haven’t completed the previous post I would suggest you to look at them before continuing.

In this post we will provide users to add inventory and display all the existing inventory. Also the user will be able to scan the barcode and get necessary detail about that product.

The datamodel for the product will look like below.

images

Most of the data in the CoreDataStack is boilerplate code and is automatically generated. The most important function in our case is insertInventory which creates an entity in the managed object context and store it in the core data stack.

CoreDataStack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//
//  CoreDataStack.swift
//  SimplyBarcode
//
//  Created by Shrikar Archak on 2/8/15.
//  Copyright (c) 2015 Shrikar Archak. All rights reserved.
//

import Foundation
import CoreData

class CoreDataStack {
    lazy var applicationDocumentsDirectory: NSURL = {
        // The directory the application uses to store the Core Data store file. This code uses a directory named "com.shrikar.SimplyBarcode" in the application's documents Application Support directory.
        let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
        return urls[urls.count-1] as NSURL
        }()

    lazy var managedObjectModel: NSManagedObjectModel = {
        // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
        let modelURL = NSBundle.mainBundle().URLForResource("SimplyBarcode", withExtension: "momd")!
        return NSManagedObjectModel(contentsOfURL: modelURL)!
        }()

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
        // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SimplyBarcode.sqlite")
        var error: NSError? = nil
        var failureReason = "There was an error creating or loading the application's saved data."
        if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
            coordinator = nil
            // Report any error we got.
            let dict = NSMutableDictionary()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason
            dict[NSUnderlyingErrorKey] = error
            error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(error), \(error!.userInfo)")
            abort()
        }

        return coordinator
        }()


    func insertInventory(productName : String, supplierName : String, quantity: Int, cost: Double, barcodeString: String,
        barcode: NSData) {
            let record = NSEntityDescription.insertNewObjectForEntityForName("Product", inManagedObjectContext: self.managedObjectContext!) as Product
            record.productName = productName
            record.supplierName = supplierName
            record.quantity = quantity
            record.cost = cost
            record.barcodeString = barcodeString
            record.barcode = barcode
            saveContext()
    }

    lazy var managedObjectContext: NSManagedObjectContext? = {
        // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
        let coordinator = self.persistentStoreCoordinator
        if coordinator == nil {
            return nil
        }
        var managedObjectContext = NSManagedObjectContext()
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
        }()

    // MARK: - Core Data Saving support

    func saveContext () {
        if let moc = self.managedObjectContext {
            var error: NSError? = nil
            if moc.hasChanges && !moc.save(&error) {
                // Replace this implementation with code to handle the error appropriately.
                // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                NSLog("Unresolved error \(error), \(error!.userInfo)")
                abort()
            }
        }
    }

}