Categories
iOS SpriteKit

Deforming sprites with SKWarpGeometryGrid in SpriteKit

SKWarpGeometryGrid is a grid based deformation what can be applied to nodes conforming to SKWarpable protocol. It defines normalised vertex positions for source and destination where source positions are un-warped geometry and destination warped geometry. Therefore, if destination vertex positions are not equal to source, the node will look deformed.

Vertex positions

Grid_vertex_positions_source
Here is a geometry grid with 4 columns and 4 rows. Positions in grid are normalised and in case of un-warped geometry both x and y-values are in range of 0 to 1. Therefore, position at the top left corner has coordinates 0,1 and the bottom right 1,0. It should be noted that when deforming a node, destination vertex positions can have x and y values larger than 1 and less than 0 – node will just look stretched.

Deforming a node

Deforming a sprite consists of two steps: creating a SKWarpGeometryGrid and applying it to a warpable node. Firstly, let’s create a function on SKWarpGeometryGrid what takes in a normalised contact position and returns a deformed grid. Normalised means that the contact point is in grid’s coordinate system.

extension SKWarpGeometryGrid {
func deform(at contactPoint: float2, radius: Float) -> SKWarpGeometryGrid {
// Make a copy of current grid positions.
let currentPositions: [float2] = {
var positions = [float2](repeating: .zero, count: vertexCount)
(0..<vertexCount).forEach({ positions[$0] = destPosition(at: $0) })
return positions
}()
// Move some of the positions in the grid close to contact point.
let destination = currentPositions.map { (gridPoint) -> float2 in
let contactDistance = gridPoint.distance(to: contactPoint)
guard contactDistance <= Float(radius) else { return gridPoint }
// If contact was very close to the grid point, move it a little bit further away from the contact point.
let gridPointChangeFactor = (Float(radius) - contactDistance) / Float(radius)
let maxDeformation: Float = 0.1
let gridPointDistanceChange = Float(maxDeformation) * gridPointChangeFactor // vector length
// Limit angle, as otherwise the edges of the crater are too far away from the center of the node.
let angleToCenter = contactPoint.angle(to: float2(x: 0.5, y: 0.5))
let maxAngleOffset = Float.pi / 4.0
let minAngle = angleToCenter - maxAngleOffset
let maxAngle = angleToCenter + maxAngleOffset
var gridPointOffsetAngle = contactPoint.angle(to: gridPoint)
gridPointOffsetAngle = min(max(gridPointOffsetAngle, minAngle), maxAngle)
return float2(x: gridPoint.x + gridPointDistanceChange * cos(gridPointOffsetAngle), y: gridPoint.y + gridPointDistanceChange * sin(gridPointOffsetAngle))
}
return replacingByDestinationPositions(positions: destination)
}
}

This function copies all the current destination vertex positions as node might be already deformed. Secondly, it loops over all the vertex positions and modifies the ones, which are fairly close to the contact point. The amount how much each vertex position is moved should depend on the distance to the contact point. The angle is calculated between the contact point and the grid position. Angle is clamped for avoiding moving vertex positions too far away from the centre point what gives more natural deformation. Magnitude and angle gives us a deformation vector for a given vertex position.

Grid deformation

Here we can see a contact point in green and moved vertex positions. In one case, angle is not limited and vertex position is moved further away (contact point, old vertex position and new vertex position line up). In the second case, angle of the offset vector is clamped and the vertex position moves to the right and it will not line up with the contact point and previous position.

The deformed geometry can be applied by setting warpGeometry property which will deform the node without an animation. For animating deformation, use warp(to:duration:).

func touchUp(atPoint position: CGPoint) {
let gridContactPoint = position.normalizedContactPoint(sprite.position, rotation: sprite.zRotation)
let grid = sprite.warpGeometry as? SKWarpGeometryGrid ?? SKWarpGeometryGrid(columns: 4, rows: 4)
let deformedGrid = grid.deform(at: float2(Float(gridContactPoint.x), Float(gridContactPoint.y)))
guard let action = SKAction.warp(to: deformedGrid, duration: 0.5) else { fatalError("Invalid deformation.") }
action.timingMode = .easeOut
sprite.run(action, withKey: "deform")
}

Finally, here is a demo app with a rotating circle and clicking anywhere around the circle will cause it to deform.

Deformation_demo.gif

Summary

SKWarpGeometryGrid adds a simple way for creating deformations in SpriteKit. The precision of the deformation is defined by the amount of vertex positions in a grid. Applying coordinate system transformations and using euclidian geometry, it is possible to create pretty cool deformations with a little bit of code.

Playground

SKWarpGeometryGridExample (GitHub) Xcode 10, Swift 4.2

References

SKWarpGeometryGrid (Apple)
SKWarpable (Apple)
Euclidian geometry (Wikipedia)

Categories
iOS Swift

Taking photos on iOS

This time we will take a look on how to take photos and browse them on iOS.

Using UIImagePickerController

Creating user interface for taking photos consists of presenting an instance of UIImagePickerController. Controller needs a delegate and source type what defines if we are going to take a photo or pick a photo from the library. But even before creating the controller it is required to call isSourceTypeAvailable(_:) class method and verifying if the source type is available. For example, it returns false if picker’s sourceType is set to UIImagePickerController.SourceType.photoLibrary and the library is empty. Makes sense, as there are no photos to pick from.

@IBAction func takePhoto(_ sender: Any) {
openPhotoPicker(withSource: .camera)
}
@IBAction func choosePhoto(_ sender: Any) {
openPhotoPicker(withSource: .photoLibrary)
}
@discardableResult private func openPhotoPicker(withSource source: UIImagePickerController.SourceType) -> Bool {
guard UIImagePickerController.isSourceTypeAvailable(source) else { return false }
let picker: UIImagePickerController = {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = source
return picker
}()
present(picker, animated: true, completion:nil)
return true
}

UIImagePickerControllerDelegate contains two methods we need to implement for handling interactions in image picker. Firstly, consuming taken or picked images and secondly, dismissing the picker. Info dictionary in imagePickerController(_:didFinishPickingMediaWithInfo:) contains quite a many values from images to metadata. All the possible keys can be seen here. As a bare minimum we need to handle editedImage and originalImage keys. If it is required to add the image to photo library, then this can be done by calling UIImageWriteToSavedPhotosAlbum(). This starts an asynchronous operation for adding the image to library. And if needed, it is possible to specify callback when this operation finishes.

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let handleImage: (UIImage?) -> () = { (image) in
self.imageView.image = image
self.imageView.isHidden = (image == nil)
if let image = image {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
}
if let image = info[.editedImage] as? UIImage {
handleImage(image)
}
else if let image = info[.originalImage] as? UIImage {
handleImage(image)
}
else {
handleImage(nil)
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
}

Privacy statements

Before going ahead and presenting the image picker it is required to add privacy statements to info.plist. Privacy - Camera Usage Description (NSCameraUsageDescription) is required for using the camera and Privacy - Photo Library Additions Usage Description (NSPhotoLibraryUsageDescription) when using UIImageWriteToSavedPhotosAlbum() for storing photos. Values of those keys are localised descriptions which are shown when app requests to use the camera or when adding the photo to the library.

Summary

Setting up user interface for taking photos is quite easy thanks to UIImagePickerController. All in all it was a three step process: configure picker, add privacy statements and handle images.

Sample app

PhotoTaker (GitHub) Xcode 10, Swift 4.2

References

UIImagePickerControllerDelegate (Apple)
NSCameraUsageDescription
NSPhotoLibraryUsageDescription

Categories
CoreAnimation iOS Swift UIKit

Custom non-interactive transition in iOS

In iOS view transitions can be interactive and non-interactive. In this post we are going to take a look on how to implement a custom non-interactive transition.

Setting up a custom transition

For setting up a custom non-interactive transition it is needed to create an animator object defining the transition and feeding it into UIKit. Before view controller is presented, we’ll need to change the UIModalPresentationStyle to custom, set delegate and with delegate method providing the custom animator to UIKit.

final class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
@objc func showView() {
let presentedViewController = PresentedViewController()
presentedViewController.modalPresentationStyle = .custom
presentedViewController.transitioningDelegate = self
present(presentedViewController, animated: true, completion: nil)
}
private let transition = CustomTransition()
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return transition
}
}

Custom animator

Custom animator object needs to conform to UIViewControllerContextTransitioning. It is required to implement a method defining the duration of the transition and method performing the transition. UIKit calls those methods and provides a UIViewControllerContextTransitioning object what gives contextual information about the transition (e.g. view controllers related to the transition). It is important to check isAnimated property for seeing if the transition should be animated at all. Secondly, it is required to call completeTransition() when transition has finished.
Let’s take a look on an example implementation of custom transition. In this particular case Core Animation is used for implementing animations. Several animations run in an animation group, and when it finishes, completeTransition() is called. Core Animation is used because of the need to rotate the presented view which is easy to do with CABasicAnimation. Just for keeping in mind that most of the simpler animations might be easier just to implement with UIView’s animate(withDuration:delay:options:animations:completion:).

final class CustomTransition: NSObject, CAAnimationDelegate, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let toViewController = transitionContext.viewController(forKey: .to) else { return }
transitionContext.containerView.addSubview(toViewController.view)
if transitionContext.isAnimated {
toViewController.view.frame = transitionContext.finalFrame(for: toViewController)
let opacity: CABasicAnimation = {
let animation = CABasicAnimation(keyPath: "opacity")
animation.duration = transitionDuration(using: transitionContext)
animation.fromValue = 0.0
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
animation.toValue = 1.0
return animation
}()
let rotation: CABasicAnimation = {
let animation = CABasicAnimation(keyPath: "transform.rotation")
animation.duration = transitionDuration(using: transitionContext)
animation.fromValue = 0.0
animation.toValue = 2.0 * 2.0 * Double.pi
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
return animation
}()
let scale: CABasicAnimation = {
let animation = CABasicAnimation(keyPath: "transform.scale")
animation.duration = transitionDuration(using: transitionContext)
animation.fromValue = 0.1
animation.toValue = 1.0
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
return animation
}()
let group: CAAnimationGroup = {
let group = CAAnimationGroup()
group.animations = [opacity, rotation, scale]
group.delegate = self
group.duration = transitionDuration(using: transitionContext)
return group
}()
self.transitionContext = transitionContext
toViewController.view.layer.add(group, forKey: "rotateScaleGroup")
}
else {
toViewController.view.frame = transitionContext.finalFrame(for: toViewController)
transitionContext.completeTransition(true)
}
}
private var transitionContext: UIViewControllerContextTransitioning? = nil
func animationDidStop(_ animation: CAAnimation, finished isFinished: Bool) {
transitionContext?.completeTransition(isFinished)
transitionContext = nil
}
}

Here is the end result.
CustomViewTransitionExample

Summary

In this blog post we took a look on how to use custom transitions when presenting a view controller. It was a matter of setting presentation style to custom and creating and providing an animator object to UIKit using a delegate.

Playground

CustomViewTransition (GitHub) Xcode 10, Swift 4.2

References

UIViewControllerContextTransitioning (Apple)

Categories
Generics Swift

Singly linked list with generics in Swift

In this post we will go over basic usage of generics in Swift by building a simple singly linked list.

Introduction to generics

Generic code is code where the functionality is described without using specific types. Meaning, the code can use any types what match with constraints (if there are any). It’s best to take a look on an example. See how separate functions can be replaced with a single implementation.

// non-generic functions
func someFunctionInt(_ values: [Int]) {}
func someFunctionString(_ values: [String]) {}
// generic
func someFunction<T>(_ values: [T]) {}
// non-generic functions
someFunctionInt([1, 2, 3])
someFunctionString(["a", "b", "c"])
// generic
someFunction([1, 2, 3])
someFunction(["a", "b", "c"])
// Type constraint
func someSortFunction<T: Comparable>(_ values: [T]) -> [T] {
return values.sorted()
}
let sorted = someSortFunction([3, 7, 5, 1])
print(sorted) // [1, 3, 5, 7]

Generic implementation defines a placeholder for a type (in angle brackets), in those examples T was used (can be something else but it is the most common placeholder). If multiple type placeholders are needed, placeholders are separated with commas. In addition, it is possible to constrain the type, for example, requiring the type to conform to comparable protocol allowing to use comparisons in the generic function’s implementation. It’s the bare minimal knowledge required for getting started with generics. There is a lot more about it.

Singly linked list

Singly linked list is a data structure where every node knows about the next node, but not about the preceding node. The benefit of such data structure is efficiency when inserting and removing nodes. On the other hand it does not allow random access of nodes.
Defining a generic linked list is quite easy. First we need a LinkedList struct storing the first node. Node stores a value and the next node. When inserting or removing nodes from the list, next property is updated. Therefore node needs to have reference semantics for making sure all the objects are pointing at the correct next object (in value semantics new instances would be created when mutating the next property and it would break the continuity of the list).

struct LinkedList<T> {
final class Node<T> {
let value: T
init(_ value: T, next: Node<T>? = nil) {
self.value = value
self.next = next
}
var next: Node<T>? = nil
}
var first: Node<T>? = nil
}

As said before, inserting and removing nodes is just a matter of updating the next properties. Therefore when inserting a node, its next node is the current node’s next node and the current node’s next node is the inserted node.

extension LinkedList {
@discardableResult func insert<T>(_ node: Node<T>, after: Node<T>) -> Node<T> {
node.next = after.next
after.next = node
return node
}
@discardableResult mutating func prepend(_ node: Node<T>) -> Node<T> {
node.next = first
self.first = node
return node
}
@discardableResult func remove(after node: LinkedList<T>.Node<T>) -> LinkedList<T>.Node<T>? {
let removed = node.next
node.next = node.next?.next
return removed
}
}

And finally, using generic linked list.

print("Populating parking lot.")
var parkingLot = LinkedList<String>()
parkingLot.prepend(LinkedList.Node("Car"))
let truck = parkingLot.prepend(LinkedList.Node("Truck"))
parkingLot.insert(LinkedList.Node("Chopper"), after: truck)
parkingLot.forEach(body: { print($0.value) })
print("Empty: \(parkingLot.isEmpty)")
/*
Populating parking lot.
Truck
Chopper
Car
Empty: false
*/
print("Rearranging parking lot.")
parkingLot.remove(after: truck)
parkingLot.forEach(body: { print($0.value) })
/*
Rearranging parking lot.
Truck
Car
*/
print("Populating numbers.")
var numbers = LinkedList<Int>()
let first = numbers.prepend(LinkedList.Node(1))
numbers.insert(LinkedList.Node(2), after: first)
numbers.forEach(body: { print($0.value) })
/*
Populating numbers.
1
2
*/

Summary

In this post we took a quick look at how to write generic code and applied that knowledge on generic version of singly linked list. It should be noted that here we used only the basics of generics and for example the linked list implementation could also benefit from associated types allowing to replace Node with for example, Element.

Playground

SinglyLinkedList (GitHub)

References

Generics in Swift (Apple)
Linked lists (Wikipedia)

Categories
iOS Swift

Sharing UI code with protocol extension

In this blog post we are going to look into how to share UI code between view controllers using protocol extension.

Problem setup

Let’s say we have two view controllers: one showing a list of items and another one showing items in a collection view. In iOS development it is common to use UITableViewController and UICollectionViewController subclasses for implementing the functionality.

final class TableViewController: UITableViewController {}
final class CollectionViewController: UICollectionViewController {}
view raw Views.swift hosted with ❤ by GitHub

What if both views do not have any items, then it would be nice to show a label indicating there is no content to show instead of a blank view. How to share code with both view controllers? Although there are multiple ways, in this case, let’s go for protocol extension.

Protocols and protocol extensions

Protocol is a set of methods, properties, and other requirements for enabling a particular functionality. In Swift, it is possible to provide a default implementation for methods and properties in a protocol. Meaning, whenever an object conforms to a protocol, it will gain an implementation of that method automatically. Otherwise the object itself must implement the method or property. This difference is presented in two code snippets where in the first one Car and Truck conform to InteriorLighting protocol and implement the interiorLightColor property themselves. In the second example the protocol is extended to have a default implementation of the property. It should be noted that both Car and Truck can still override default implementation themselves if needed.

import UIKit
protocol InteriorLighting {
var interiorLightColor: UIColor { get }
}
struct Car: InteriorLighting {
var interiorLightColor: UIColor {
return .white
}
}
struct Truck: InteriorLighting {
var interiorLightColor: UIColor {
return .white
}
}
print(Car().interiorLightColor) // UIExtendedGrayColorSpace 1 1
print(Truck().interiorLightColor) // UIExtendedGrayColorSpace 1 1

import UIKit
protocol InteriorLighting {
var interiorLightColor: UIColor { get }
}
extension InteriorLighting {
var interiorLightColor: UIColor {
return .white
}
}
struct Car: InteriorLighting {}
struct Truck: InteriorLighting {}
print(Car().interiorLightColor) // UIExtendedGrayColorSpace 1 1
print(Truck().interiorLightColor) // UIExtendedGrayColorSpace 1 1

Adding banner view when there is no content

Let’s now go back to TableViewController and CollectionViewController and add a banner view for both of those view controllers with protocol extension. Firstly, it is needed to define the protocol. Let’s name it as EmptyViewBanner. It has two properties: one for defining the string what to show and the other one for providing a container view for the banner as the protocol itself does not know anything about the view controllers. This protocol has a setter what mutates the conforming object. Therefore, let’s restrict the protocol to class only for requiring the conforming type to have reference semantics.

protocol EmptyViewBanner: AnyObject {
var bannerContainerView: UIView { get }
var emptyViewText: String { get set }
}

Next step is to provide a default implementation for the emptyViewText property. Its implementation will add a label to view hierarchy for showing the text. As protocol can’t have stored properties, it needs to use some other way for keeping a reference to the label. Having a tag and looking up by it will suffice.

extension EmptyViewBanner {
var emptyViewText: String {
get {
guard let label = bannerContainerView.viewWithTag(10000) as? UILabel else { return "" }
return label.text ?? ""
}
set {
guard newValue.isEmpty == false else {
bannerContainerView.viewWithTag(10000)?.removeFromSuperview()
return
}
if bannerContainerView.viewWithTag(10000) == nil {
let label = UILabel()
label.numberOfLines = 0
label.tag = 10000
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
bannerContainerView.addSubview(label)
label.leadingAnchor.constraint(equalToSystemSpacingAfter: bannerContainerView.safeAreaLayoutGuide.leadingAnchor, multiplier: 1.0).isActive = true
bannerContainerView.safeAreaLayoutGuide.trailingAnchor.constraint(equalToSystemSpacingAfter: label.trailingAnchor, multiplier: 1.0).isActive = true
label.centerYAnchor.constraint(equalTo: bannerContainerView.safeAreaLayoutGuide.centerYAnchor).isActive = true
}
guard let label = bannerContainerView.viewWithTag(10000) as? UILabel else { fatalError() }
label.text = newValue
}
}
}

Lastly, both view controllers need to conform to EmptyViewBanner protocol and provide container views for the banner.

extension CollectionViewController: EmptyViewBanner {
var bannerContainerView: UIView {
return collectionView
}
}
extension TableViewController: EmptyViewBanner {
var bannerContainerView: UIView {
return tableView
}
}

Now it is possible to set text to both of the view controllers and protocol extension will take care of managing the label.

let contactsViewController: CollectionViewController = …
let historyViewController: TableViewController = …
contactsViewController.emptyViewText = "There are not any contacts"
historyViewController.emptyViewText = "There is no history available"

EmptyBannerView

Summary

In this blog post we looked into how to use protocol extension in Swift for sharing UI code. How to add a label to view hierarchy for showing a banner and how to keep a reference to it without using stored property.
Thank you for reading.

Playground

ProtocolExtensionForAddingUIElements (GitHub)
Xcode 10.0, Swift 4.2

References

Protocols (Swift.org)

Categories
CoreData Swift

Storing data with CoreData

CoreData is a framework for managing object graphs and storing them on disk. It is much more than just offering a persistent storage, therefore the rich API it provides, is meant to be used app-wide. In this blog post we’ll look into how to initialise CoreData storage, store some data in it and fetching it.

Core data model

First step is to add a Core Data model which will describe model objects, their relationships and properties. In Xcode we’ll go to File -> New -> File… and then select Data Model.
adding_core_data_model

We are going to continue working on sample app named Planets (from previous post). It needs an entity named Planet which has 3 properties: name, url and position (defines sort order in the app). By default Core Data will autogenerate a model object for our entity Planet we just defined. Therefore all we need to do is creating an entity and adding three properties to the entity.
core_data_model

Initialising CoreData stack

The simplest way for initialising Core Data stack is to use NSPersistentContainer and initialising it with a name of the Core Data model file we just created in the previous step. After creating the container, it needs to be loaded which will read the Core Data model file and sets up a persistent store.

convenience init(name: String)
func loadPersistentStores(completionHandler block: @escaping (NSPersistentStoreDescription, Error?) -> Void)

In the sample app we are going to use subclass of NSPersistentContainer named CoreDataStore which contains extra methods used in a moment.

Storing data

Adding data contains of two steps: making changes in NSManagedObjectContext and then saving it. NSManagedObjectContext is a scratch pad where to make changes in your object graph. All the changes will be stored in memory until save is called.
For adding a new entity we will use a method in our CoreDataStore.

func insertNewEntity(named name: String) -> NSManagedObject {
return NSEntityDescription.insertNewObject(forEntityName: name, into: viewContext)
}

This will add a new empty entity to managed object context. After that, we’ll fill properties with appropriate values and then call save.
func tryStoringDefaultPlanets() {
// dataStore is an instance of NSPersistentContainer subclass CoreDataStore.
guard dataStore.count(for: "Planet") == 0 else { return }
// Insert new entities into managed object context.
let names = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
let paths = ["https://en.wikipedia.org/wiki/Mercury_(planet)&quot;, "https://en.wikipedia.org/wiki/Venus&quot;, "https://en.wikipedia.org/wiki/Earth&quot;, "https://en.wikipedia.org/wiki/Mars&quot;, "https://en.wikipedia.org/wiki/Jupiter&quot;, "https://en.wikipedia.org/wiki/Saturn&quot;, "https://en.wikipedia.org/wiki/Uranus&quot;, "https://en.wikipedia.org/wiki/Neptune"%5D
zip(names, paths).enumerated().forEach { (offset, element) in
guard let planet = dataStore.insertNewEntity(named: "Planet") as? Planet else { return }
planet.position = Int64(offset)
planet.name = element.0
planet.url = URL(string: element.1)
}
// Save changes in the managed object context what at the moment contains added Planets.
dataStore.save()
}

Fetching data

In our sample app, there is a simple table view displaying a list of planets. For displaying data efficiently, Core Data has a class NSFetchedResultsController. It uses NSFetchRequest objects for fetching, sorting and filtering results. Our class CoreDataStore has a convenience method for creating fetched results controller for any type of entities and PlanetManager has a getter for returning controller for Planet entities.

final class CoreDataStore: NSPersistentContainer {
func fetchedResultsController(named name: String, sortDescriptors: [NSSortDescriptor], predicate: NSPredicate? = nil, sectionNameKeyPath: String? = nil) -> NSFetchedResultsController<NSFetchRequestResult> {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: name)
if let predicate = predicate {
request.predicate = predicate
}
request.sortDescriptors = sortDescriptors.isEmpty ? nil : sortDescriptors
return NSFetchedResultsController(fetchRequest: request, managedObjectContext: viewContext, sectionNameKeyPath: sectionNameKeyPath, cacheName: nil)
}
}
final class PlanetManager {
lazy var planetsController: NSFetchedResultsController<Planet> = {
let descriptors = [NSSortDescriptor(key: "position", ascending: true)]
return dataStore.fetchedResultsController(named: "Planet", sortDescriptors: descriptors) as! NSFetchedResultsController<Planet>
}()
}

Let’s see how to hook up fetched results controller to table view controller. Before fetched controller is used for fetching data, it needs to perform a fetch. For a simple list view it is pretty straight-forward: getting count and fetching an object for index path.
private func fetchPlanets() {
do {
try planetsController.performFetch()
tableView.reloadData()
}
catch {
NSLog("Fetching failed with error \(error as NSError).")
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return planetsController.sections?[0].numberOfObjects ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PlanetCellIdentifier", for: indexPath)
cell.accessoryType = .disclosureIndicator
cell.textLabel?.text = planetsController.object(at: indexPath).name
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
scenePresenter?.presentDetailedInfo(for: planetsController.object(at: indexPath))
}

Summary

In this blog post we looked into how to initialise Core Data stack with NSPersistentContainer, storing some data in it with NSManagedObjectContext and fetching results with NSFetchedResultsController. It is the most basic usage of CoreData and covers a tiny bit what Core Data can do. Apple has a pretty good documentation what covers much more compared to what was described here (see links to Core Data classes in the previous sections).

Example

Planets (GitHub)

References

CoreData (Apple)

Categories
iOS Swift UIKit

View coordination with responder chain

When building iOS apps it is important to think about how to structure an app and how to connect all the pieces. A typical app has multiple interaction flows and in this post I am going to represent a way of how to decouple views and how to navigate from one view to another using responder chain.

Coordinating view presentation

Let’s take a look on the example app named “Planets” what has a structure:
Blogi - planets.001
There are a several view controllers and some of them pass information to the next one. In object oriented programming world, it is important to reduce dependencies between objects and having preferably only one responsibility for an object (see separation of concerns and single responsibility principle). Therefore, when a view would like to present another view (e.g. user presses on a button what triggers presenting a new view) it is preferred the view not to know the exact view controller what should be presented and how it should be presented. Instead, it should forward it to a separate entity what deals with loading views, injecting dependencies and presenting them. With that kind of pattern it is possible to forward required information to that entity and only it will know the type of the view controller what to present – reducing coupling between views themselves and giving a more modular architecture to an app.
In the sample app Planets the view presenter’s interface is defined by a protocol ScenePresenting.

protocol ScenePresenting {
func presentDetailedInfo(for planet: Planet)
func presentPlanetList()
func presentURL(_ url: URL)
}

SceneManager conforms to that protocol. It knows how to load views, what dependencies to inject and how to present views. Having presentation logic separated from the views, it is easier to later on change the interaction flows in the app due to reduced dependencies. Compare it with app architecture where view controllers themselves load and present view controllers.
What if app has way more views to represent? The presentation logic might get a quite long. One solution would be to have multiple protocols for different interaction ares of the app and having multiple objects like SceneManager specialised to a specific area.

Tapping into responder chain

Responder chain is a dynamic list of UIResponder objects where events are passed from responder to responder. If this is a new concept for you, then I suggest to quickly read through the overview section of responder chains here.
UIView and UIViewController are subclasses of UIResponder and are part of single or multiple responder chains (the list of responders in any chain are defined by the rules in UIKit). Responder chain always ends up in UIApplication object and if the app’s delegate is also UIResponder, the chain continues to its delegate as well.
This knowledge gives us an opportunity to expand the chain further and inserting SceneManager to the end of the chain allowing us to access it from any of the view controllers currently on screen.
It is required to just override the var next: UIResponder? { get } property in AppDelegate (AppDelegate needs be a subclass of UIResponder) and then returning an object what conforms to the protocol ScenePresenting. In the current case it is going to be an instance of SceneManager.

final class AppDelegate: UIResponder, UIApplicationDelegate {
private var sceneManager: SceneManager? = nil
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
guard let window = window else { fatalError() }
sceneManager = SceneManager(window: window)
return true
}
override var next: UIResponder? {
return sceneManager
}
}

With this change, SceneManager is now part of all the responder chains, but accessing it is a bit cumbersome. For solving this it is easy to add a convenience property to UIResponder what just goes through the chain and returns it. SceneManager is now available in all the responders and its type is erased (caller just sees an object conforming to the protocol and does not see the object’s type).
extension UIResponder {
var scenePresenter: ScenePresenting? {
var current: UIResponder? = self
repeat {
if let presenter = current as? ScenePresenting {
return presenter
}
current = current?.next
} while current != nil
return nil
}
}

Using protocol instead of SceneManager allows to hide the implementation details and breaks apart the dependency graph for users of this property. Moreover it allows to replace the SceneManager with any other object conforming to the protocol at any time in the future – separation of concerns.

Presenting new views

Presenting views becomes now much simpler to manage. In addition, the scene presenter object is accessible from any new view controller automatically. Compare it to injecting SceneManager to presented view controllers which requires all the view controllers to have a way of storing a reference to it and a way of injecting it. All this can be left out when it is part of responder chain.

@IBAction func goToList(_ sender: Any) {
scenePresenter?.presentPlanetList()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
scenePresenter?.presentDetailedInfo(for: planets[indexPath.row])
}
@IBAction func show(_ sender: Any) {
scenePresenter?.presentURL(planet.url)
}
view raw Examples.swift hosted with ❤ by GitHub

Summary

We looked into a simple app consisting of several scenes. Having a presentation logic hidden into a separate object allowed us to decouple views from each other what reduces dependency graph for all the views. Inserting an object, responsible of presenting all the scenes, into responder chain gave us a simple, scalable and concise way of triggering view navigation.

Example

Planets (GitHub)

References

Understanding event handling, responders and the responder chain (Apple)
Separation of concerns (Wikipedia)
Single responsibility principle (Wikipedia)

Categories
iOS

Using CCHmac for creating message authentication codes

This is a second part of the first post about hashing data using SHA256. Here we will look into CCHmac (Hash-based Message Authentication Code) functions and see how to use it for creating authentication codes what can be used for data integrity checks and authentication of a message.

Message authentication codes

Hash-based message authentication code enables validating messages sent between two parties. For achieving that, the sender will use secret key for creating an authentication code of the message. Then transmits the message and the code to the other party. Then the receiver will use the same secret key (only they both know the key) for creating an authentication code of the received message. If the received authentication code matches with the created one, the receiver can be sure of the message’s integrity.

CCHmac interface

There are 3 functions which are used together for creating an authentication code. These are: CCHmacInit(), CCHmacUpdate() and CCHmacFinal(). Note that the update function can be called multiple times for processing the data in chunks. In addition, there is a convenience function what internally creates CCHmacContext object and uses listed functions for initialising, updating and finalising the process of creating an authentication code. We will concentrate on the convenience function.

/*!
@function CCHmac
@abstract Create the Message Authentication Code.
@param algorithm HMAC algorithm to perform.
@param key Raw key bytes.
@param keyLength Count of raw key bytes. It can also be zero.
@param data Raw data bytes.
@param dataLength Count of data bytes.
@param macOut Output buffer allocated by caller.
*/
void CCHmac(CCHmacAlgorithm algorithm, const void *key, size_t keyLength, const void *data, size_t dataLength, void *macOut);
view raw CCHmac.h hosted with ❤ by GitHub

Arguments define the hashing algorithm, secret key, input data and an output buffer. It is important to note that the output buffer needs to be preallocated and the length depends on the chosen algorithm (for example SHA256 requires a buffer with length equal to CC_SHA256_DIGEST_LENGTH).

Data extension for CCHmac in Swift

import Foundation
import CommonCrypto
extension Data {
enum Algorithm {
case md5
case sha1
case sha224
case sha256
case sha384
case sha512
var digestLength: Int {
switch self {
case .md5: return Int(CC_MD5_DIGEST_LENGTH)
case .sha1: return Int(CC_SHA1_DIGEST_LENGTH)
case .sha224: return Int(CC_SHA224_DIGEST_LENGTH)
case .sha256: return Int(CC_SHA256_DIGEST_LENGTH)
case .sha384: return Int(CC_SHA384_DIGEST_LENGTH)
case .sha512: return Int(CC_SHA512_DIGEST_LENGTH)
}
}
}
}
extension Data.Algorithm: RawRepresentable {
typealias RawValue = Int
init?(rawValue: Int) {
switch rawValue {
case kCCHmacAlgMD5: self = .md5
case kCCHmacAlgSHA1: self = .sha1
case kCCHmacAlgSHA224: self = .sha224
case kCCHmacAlgSHA256: self = .sha256
case kCCHmacAlgSHA384: self = .sha384
case kCCHmacAlgSHA512: self = .sha512
default: return nil
}
}
var rawValue: Int {
switch self {
case .md5: return kCCHmacAlgMD5
case .sha1: return kCCHmacAlgSHA1
case .sha224: return kCCHmacAlgSHA224
case .sha256: return kCCHmacAlgSHA256
case .sha384: return kCCHmacAlgSHA384
case .sha512: return kCCHmacAlgSHA512
}
}
}
extension Data {
func authenticationCode(for algorithm: Algorithm, secretKey: String = "") -> Data {
guard let secretKeyData = secretKey.data(using: .utf8) else { fatalError() }
return authenticationCode(for: algorithm, secretKey: secretKeyData)
}
func authenticationCode(for algorithm: Algorithm, secretKey: Data) -> Data {
let hashBytes = UnsafeMutablePointer<UInt8>.allocate(capacity: algorithm.digestLength)
defer { hashBytes.deallocate() }
withUnsafeBytes { (bytes) -> Void in
secretKey.withUnsafeBytes { (secretKeyBytes) -> Void in
CCHmac(CCHmacAlgorithm(algorithm.rawValue), secretKeyBytes, secretKey.count, bytes, count, hashBytes)
}
}
return Data(bytes: hashBytes, count: algorithm.digestLength)
}
}
view raw CCHmac.swift hosted with ❤ by GitHub

The method for creating authentication code is func authenticationCode(for algorithm: Algorithm, secretKey: Data) -> Data what is very easy to use for creating raw message authentication code. It can be converted into string by using Data's base64EncodedString().

Example project can be found on GitHub (CommonCryptoExample).

References

Wikipedia: HMAC
man page of CCHmac

Categories
iOS Xcode

Hashing data using CommonCrypto and SHA256

Looking for hashing data using CryptoKit? Please navigate to here.

In this post we will look into how to add CommonCrypto to a Xcode project and how to generate hash using SHA256.

Adding CommonCrypto as a module

Note: Since Swift 4.2, this step is not necessary and manually added CommonCrypto module must be removed.

CommonCrypto library can be added in two ways: importing it in the Objective-C bridging header or by using module maps.
The first option makes sense for projects having both Objective-C and Swift code. In this case Objective-C bridging header is already part of the project and therefore adding #import to the bridging header is the quickest way.
The second option is more suitable for pure Swift projects as it enables to avoid adding the bridging header (although it is up for everyone’s preference).
Adding CommonCrypto as a module consists of two steps. Firstly, we need to create a folder named ‘CommonCrypto’ in the same folder as the Xcode project file is. Then we need to create a file ‘module.map’ and save it to ‘CommonCrypto’ folder.

module CommonCrypto [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
export *
}
view raw module.map hosted with ❤ by GitHub
CommonCryptoModuleInProject

Secondly, we need to open the project in Xcode, then navigating to ‘Build Settings’ of the target and adding $(PROJECT_DIR)/CommonCrypto/ to ‘Import Paths’.

CommonCryptoImportPaths

That’s it, now Xcode knows where the module is located and it can be imported in Swift files.

Hashing data using SHA256 algorithm

CommonCrypto contains a function named CC_SHA256(…) what takes in data, the count of bytes and gives a pointer to the hash of the data. As the function operates on the data, it makes sense to extend Data. We’ll add a function what can be later on extended for adding support for other hashing algorithms as well (see here for other algorithms).

import Foundation
import CommonCrypto
extension Data {
enum Algorithm {
case sha256
var digestLength: Int {
switch self {
case .sha256: return Int(CC_SHA256_DIGEST_LENGTH)
}
}
}
func hash(for algorithm: Algorithm) -> Data {
let hashBytes = UnsafeMutablePointer<UInt8>.allocate(capacity: algorithm.digestLength)
defer { hashBytes.deallocate() }
switch algorithm {
case .sha256:
withUnsafeBytes { (buffer) -> Void in
CC_SHA256(buffer.baseAddress!, CC_LONG(buffer.count), hashBytes)
}
}
return Data(bytes: hashBytes, count: algorithm.digestLength)
}
}
if let someData = "Random string".data(using: .utf8) {
let hash = someData.hash(for: .sha256)
print("hash=\(hash.base64EncodedString()).")
}
// hash=LclzKS0NtZFSuwQF5H2FpTralr75LsjrnE3et2LxkHs=.
view raw Hashing.swift hosted with ❤ by GitHub

Example project can be found on GitHub (CommonCryptoExample).

If this was helpful, please let me know on Mastodon@toomasvahter or Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.

Categories
Generics iOS

Making a property observable from outer scope using generic class Observable

We will look into how to make a property observable using a separate class managing the observers. It is an alternative and simple way of observing property changes without using ReactiveSwift, Key-Value Observing or anything else similar. It can be an excellent glue between Model and View Model in MVVM or between View and Presenter when using VIPER architecture.

Creating a class Observable

final class Observable<T> {
init(_ value: T) {
self.value = value
}
var value: T {
didSet {
changeHandlers.forEach({ $0.handler(value) })
}
}
typealias ChangeHandler = ((T) -> Void)
private var changeHandlers: [(identifier: Int, handler: ChangeHandler)] = []
/**
Adds observer to the value.
- parameter initial: The handler is run immediately with initial value.
- parameter handler: The handler to execute when value changes.
- returns: Identifier of the observer.
*/
@discardableResult func observe(initial: Bool = false, handler: @escaping ChangeHandler) -> Int {
let identifier = UUID().uuidString.hashValue
changeHandlers.append((identifier, handler))
guard initial else { return identifier }
handler(value)
return identifier
}
/**
Removes observer to the value.
- parameter observer: The observer to remove.
*/
func removeObserver(_ observer: Int) {
changeHandlers = changeHandlers.filter({ $0.identifier != observer })
}
}

The class Observable holds a value what can be of any type. Now when the value is store by the class itself we can use Swift’s property observer and then calling change handlers. This allows creating an object with observable properties and observing those properties from other objects. Moreover, it is possible to remove any of the added observers.
Let’s take a look on an example of class “Pantry” what has a property holding array of jams. In the example we will add two observers: one reacting to changes and the other one what will also react to the initial value. When one of the observer is removed and the array of jams changes, only one of the observers is triggered.

final class Pantry {
let jams = Observable([Jam(flavour: .apple)])
func add(jam: Jam) {
jams.value.append(jam)
}
}
struct Jam {
enum Flavour: String {
case apple, orange
}
let flavour: Flavour
init(flavour: Flavour) {
self.flavour = flavour
}
}
let pantry = Pantry()
print("Adding count and contents observers.")
let observer = pantry.jams.observe { (jams) in
print("Pantry now has \(jams.count) jars of jam.")
}
pantry.jams.observe(initial: true) { (jams) in
let contents = jams.map({ $0.flavour.rawValue }).joined(separator: ", ")
print("Jams in pantry: \(contents)")
}
print("Adding jam to pantry.")
pantry.add(jam: Jam(flavour: .orange))
print("Removing count observer.")
pantry.jams.removeObserver(observer)
print("Adding jam to pantry.")
pantry.add(jam: Jam(flavour: .apple))
/*
Adding count and contents observers.
Jams in pantry: apple
Adding jam to pantry.
Pantry now has 2 jars of jam.
Jams in pantry: apple, orange
Removing count observer.
Adding jam to pantry.
Jams in pantry: apple, orange, apple
*/

Today we learned how to very easily make a property observable from outer scope of the object owning the property.
Thank you for reading.

Download ObservableProperty playground.