Making an Interactive Card based UI using Swift (Part 2 / 2)

In the first part of this tutorial we set up the view controller and created a Glide class where we wrote code regarding segmentation, calculated the segmentation heights and implemented the pan gesture recognizer. In this part we will do the following things:

  1. Implement animations from one state to another.
  2. Animate alpha value with user’s swipe.
  3. Figure out a way to detect scrollViews inside the card view controller and handle the scroll view’s pan gesture and the card’s panGesture which we have implemented previously.

Continue reading “Making an Interactive Card based UI using Swift (Part 2 / 2)”

Making an Interactive Card based UI using Swift (Part 1/2)


Most apps nowadays use this card based UI to pop up information or show an action menu etc. Twitter, Instagram, Facebook all are using some sort of a multi-state, interactive, gesture based card flow to show information to users. I have always been intrigued by such a design element and thought I should try building one from scratch.

While building this, I also wanted to make sure that I make this in such a way that people could use it. As in if I ever want to release this as a framework, I could easily do it. So while I have not released this project as a framework, I have tried to code it in such a way to practice framework building skills and make it reusable.

The entire project is available on my Github here.

THE IDEA:

The whole project revolved around how reusable, and quickly a user can set up a card UI. There were few principles that this project had to follow:

  1. Make sure that the configuration and set up is quick.
  2. User should get two options. Segmented(multi states) or non segmented(dual states). (more on this later)
  3. Granular control over card visible height for each state.
  4. The gestures need to be smooth and intuitive / animating the background alpha values as well.
  5. The ability to show the card floating at the bottom as a closed state. (Something we see in Maps app, Uber etc)
  6. The ability to detect a scrollView inside the controller and switch between scrollView & Pan Gesture recognizer at right times.

Continue reading “Making an Interactive Card based UI using Swift (Part 1/2)”

Solving Min Stack Problem using Swift

It’s been a while since I last posted an article on an algorithm and data structure problem. This time I decided to solve the Min Stack problem. In Min Stack you need to find the minimum element inside a stack in constant time. An alternate question is Max Stack where you have to find the maximum element in a stack. Both are pretty similar conceptually.

The problem explicitly states that each stack method should run at constant time – O(1).

This is the problem statement:

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

  • push(x) — Push element x onto stack.
  • pop() — Removes the element on top of the stack.
  • top() — Get the top element.
  • getMin() — Retrieve the minimum element in the stack.

Before continuing, make sure you try this problem yourself.

Continue reading “Solving Min Stack Problem using Swift”

Getting started with FaceID/TouchID and LocalAuthentication using Swift

Since 2013, all iPhones have been launched with some sort of biometric sensors. From iPhone 5s to iPhone 8, Apple embedded a Touch ID sensor in the home button and from iPhone X onwards they started using Face ID to detect user’s face before unlocking the device.

Apple provides APIs for developers to use these security features in their apps as well. Today I will talk about how to go about setting up biometric security features in your iOS app.

Continue reading “Getting started with FaceID/TouchID and LocalAuthentication using Swift”

Making a Tinder-esque Card Swiping interface using Swift

 

Tinder – we all know that dating app where you can just reject or accept someone by swiping right or left. BAM! The whole card swiping idea is now used in tons of apps. It’s a way to show data if you have grown tired of using table views and collection views. There are tons of tutorial on this and this project took me good bit of time.

You can check out the full project on my Github.

First of all, I would like to give credit to Phill Farrugia’s medium post on this and then Big Mountain Studio’s YouTube series on a similar topic. So how do we go about making this interface. I got quite a lot of help from Phill’s medium post on this front. Basically the idea is to create UIViews and insert them as subviews in a container view. Then using the index we will give each UIView some horizontal and vertical inset and tweak its width a bit. Then when we swipe away one card, all the views frames will be rearranged according to the new index value.

Continue reading “Making a Tinder-esque Card Swiping interface using Swift”

Creating Pull to Dismiss / Pull to Reach animation using Swift

One of my most used app on my iPhone is Bear app. It’s a beautiful and simple notes-taking app with tons of neat UI / UX features. One of which is being able to pull down on a scroll view to dismiss a view or select a button. As phones are getting taller, buttons on the top navigation bar are getting difficult to access using just one hand. Such gestures help users access these buttons just by swiping down or scrolling down on a scroll view which is embedded in collection view or tableviews by default.

Not only accessing navigation items, you can dismiss views containing scroll views by similar gestures. I decided to create such an animation and in this post I will take you through the entire process of analyzing the animation and then building it from scratch.

Complete project is available on GitHub. I have also incorporated protocol / delegate so that I can communicate between the pop up view and the controller. More on this later.

The project also contains some code through which I am setting up the view controller, applying dark view on the background and animating the pop up view as the user taps on the “Action” button in the top navigation bar. We are going to dismiss this view by using scroll view which is embedded in that view.

I am creating the pop up view in a separate file that goes by the name of ActionMenu. I have wrapped it in a NSObject subclass. The entire animation of the pop up view appearing from the bottom of the screen, creating the UI components and the entire code for this particular animation is written in this NSObject class file. Through the use of encapsulation, we are creating an instance of this class in the view controller and calling the configureActionMenu() and showActionMenu() functions when the “Action” button is tapped.

Continue reading “Creating Pull to Dismiss / Pull to Reach animation using Swift”

How to create Twitter card-like menu using Swift (Part 1)

Let’s create this Twitter card-like menu interface that you can invoke by tapping on the three dots on the top right hand cornerwhen you visit someone’s profile.  The initial setup is simple by creating a custom UIView which you can populate with buttons or a table view or whatever you want. I will go over that bit some day later. The main topic of discussion will be the gesture and dragging.

Continue reading “How to create Twitter card-like menu using Swift (Part 1)”

Solving longest consecutive sequence in an array using Swift

This question is asked quite often in technical interview . The problem is this:

Write a function that takes in an unsorted array of integers and returns the longest range or longest consecutive sequence. For example:

let array = [3,2,4,5,6,7,12,10,8,9,21,15,11,13,16,19,20,19]

In this array there are 18 elements, however the longest consecutive goes from 2 to 13. You can simply eye ball the above array and see consecutive numbers from 2 all the way till 13. Then you have another range from 19 to 21 and another even smaller one that goes from 15 to 16.

The function should return the start and end values of the sequence.

I strongly urge to first try this problem out before checking out my version of this solution given below.

Alright, now let’s dive in to the solution. In my version of this solution, I am using only one Hash Map or Dictionary.The dictionary is of type [Int : Bool]. When we have used an integer successfully in creating a sequence the bool value should become true.

Here is the function signature:

func findLongestRange(in array: [Int]) -> String {

Here I am initializing the dictionary and three variables to keep track of the longest sequence and in the for loop, I am giving value of false to all the entries of the dictionary.

 var numbersDic = [Int: Bool]()
      
        
        var longestSequence = 0
        var recordInitialNumber = 0
        var recordLastNumber = 0
        
        if array.count <  1 {
            return "No Sequence Found"
        }
      
        // Adding the numbers as keys with Bool as the value in the dictionary
        for n in array {
            numbersDic[n] = false
        }
      
for n in array {
           
            if ( numbersDic[n]! ) {
                continue
            }
            var previousVal = n - 1
            var nextVal = n + 1
            
            numbersDic[n] = true
            
            while numbersDic[previousVal] != nil {
                numbersDic[previousVal] = true
                previousVal = previousVal - 1
            }
            
            
             //Checking if a next value is available
            while numbersDic[nextVal] != nil {
                numbersDic[nextVal] = true
                nextVal = nextVal + 1
            }

This is the meat of the code. In this part, we are essentially first checking if the number we have landed on is already used in some other sequence by checking its value. If its true, we continue with the next iteration of the loop otherwise we continue. Then we are are setting previousVal and nextValue as current value (n) – 1 and current value + 1 respectively.
By using two while loops, we are first looking for the previous value to the current number in the hash map. If the value for it exists or the key is available, the bool value is switched to true. If there is no value in the dictionary for the previousVal key the while loop ends and goes to the next loop where we check the next value in the loop. Again the same thing, adding 1 to the nextVal and checking its presence in the hash map.

Then at the end we are checking if the current two values of nextValue and previousValue has the highest amount of numbers between them by taking the difference and returning a string:

//Checking longest sequence
            
            let difference =  (nextVal - 1) - (previousVal + 1)
           
            if (difference > longestSequence) {
                longestSequence = difference
                recordInitialNumber = previousVal + 1
                recordLastNumber = nextVal - 1
                
            } 
          return "The longest sequence starts at \(recordInitialNumber) and ends at  \(recordLastNumber)"

This is the output you get when you run this code:

The Longest sequence starts at 2 and ends at 13

Checking this algorithm in leetcode returns this result:

 

Solving 3SUM problem using Swift

The 3Sum problem is often asked during technical interviews and the problem at first seems quite tough but it’s got a pretty similar taste to 2Sum problem.

Here is the problem: You are given a sorted array, and you need to find three numbers in the array that can add up to a particular sum which is also given to you.

I would strongly urge everyone to first try solving the 2Sum problem where it requires you to find 2 numbers that add up to give you the given sum and similarly practice this problem before continuing to the solution given below. 

So first lets start with function signature:

func threeSumProblem(for array: [Int], sum: Int) -> Bool

The function takes in the sorted array of type Int and a Sum integer and returns a Bool.

func threeSumProblem(for array: [Int], sum: Int) -> Bool
    {
        var complement = 0
        var lowIndex = 0
        var highIndex = array.count - 1

Firstly, I am initializing three variables – complement, lowIndex & highIndex. To solve the 3Sum problem here is the method I am using:  If the array is say [1,4,6,4] and sum is 11, then we will first hold on to first number which in this case is 1, and then using linear pointer method on the remaining array [4,6,4]. Here we will have a pointer which will start from 4 with one index more than the number we holding on to, and the high pointer will start with index of array.count – 1. (The right hand side)

for (index, element) in array.enumerated() {
            lowIndex = index + 1
            complement = sum - element
            while (lowIndex < highIndex) 
                { if (array[lowIndex] + array[highIndex] > complement ) {
                    highIndex -= 1
                }else if (array[lowIndex] + array[highIndex] < complement) {
                    lowIndex += 1
                }else {
                    print(element, array[lowIndex], array[highIndex])
                    return true
                }
            }
            
             lowIndex = 0
             highIndex = array.count - 1
           
        }

Next, we will start a for loop which will give us the element and the index of that element in the sequence, hence using array.enumerated() . Then inside the for loop, I am setting lowIndex to current index + 1. We also set complement by subtracting the current element we are on with the sum passed in the function by the user.

Then we have another loop inside this for loop. This time it’s a while loop. The while loop will keep running until the two pointers cross over.

Inside the while loop, we have three if statements:

 if (array[lowIndex] + array[highIndex] > complement ) {
                    highIndex -= 1
                }else if (array[lowIndex] + array[highIndex] < complement) {
                    lowIndex += 1
                }else {
                    print(element, array[lowIndex], array[highIndex])
                    return true
                }

Now the problem has been converted in to 2sum. We will check if the two numbers sum is greater than complement, if yes, then move the highIndex pointer by 1 to the left. Similarly, if the sum of two numbers is less than the complement, then move the lowIndex pointer by 1 to the right. Else, if the sum of two numbers is equal to complement, then return true.

After this if statement, we are setting the lowIndex and highIndex back to 0 and array.count – 1.

Next call this function:

let array = [4,3,5,1,5]
print(threeSumProblem(for: array, sum: 14))

The output for this is:

//output
4 5 5
true

This is how you can solve this algorithm. This particular solution is O(n^2) mainly as we are using two nested loops.

Creating a NSItemProvider for custom model class (Drag & Drop API)

For a project that I will start working on this summers, I am thinking about implementing this feature where you can drag and drop one or multiple items on a view (circleView in this tutorial) and download all those items from the web. The idea of using drag and drop is nothing new in iOS and with iOS 11, Apple has introduced a specific API for users to do just this.

This API allows users to drag items within the app or from one app to another. On iPhones you can only drag the items within the app  while on iPad with the help of split view you can drag items from one app to another.

The drag and drop API is extremely easy to use and configuring it takes just few minutes. There are two separate protocols that deal with drag and drop. Also there is a UITableViewDragDelegate and UITableViewDropDelegate for dragging and dropping items between table views or within same table view.

NSItemProvider is a wrapper that creates a UIDragItem. Essentially, if you want to drag and drop items of type Strings, then you first have to wrap it with an itemProvider that will convert the data to NSString and create a UIDragItem. Then when you drop the item, it will convert it from NSString to String. Apple provides ItemProvider for types like UIImage, NSURL, NSString etc

If you are populating a table view with items of custom class then in order to drag and drop these items you have to use a custom NSItemProvider. In order to do this, you need to conform your model class to NSItemProviderReading, NSItemProviderWriting.

final class PodcastModelData: NSObject, Codable, NSItemProviderReading, NSItemProviderWriting {

Make sure to use NSObject and Codable. Codable protocol is a combination of two other protocols – Encodable & Decodable. We will use Codable to convert our object to JSON data and then when we drop it at the destination, it will revert back to the model class object.

final class PodcastModelData: NSObject, Codable, NSItemProviderReading, NSItemProviderWriting {
   
    
  // 1  
    var collectionName : String?
    var feedUrl: String?
    var artworkUrl100: String?
  // 2  
     init(collectionName: String, feedURL: String, artworkURL100: String) {
        self.collectionName = collectionName
        self.feedUrl = feedURL
        self.artworkUrl100 = artworkURL100
    }
   //3 
    static var writableTypeIdentifiersForItemProvider: [String] {
        return [(kUTTypeData) as String]
    }
    
// 4
    func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
        
        
        let progress = Progress(totalUnitCount: 100)
        // 5
        
        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted
            let data = try encoder.encode(self)
            let json = String(data: data, encoding: String.Encoding.utf8)
            progress.completedUnitCount = 100
            completionHandler(data, nil)
        } catch {
     
            completionHandler(nil, error)
        }
        
        return progress
    }

Let’s break down the above code:

  1. Class properties – three variables all of type of strings
  2.  simple initializer.
  3. First method to conform to –  ‘writableTypeIdentifiersForItemProvider‘ method returns an array of type of identifiers as Strings. Again it’s array so you can give them multiple identifiers but make sure that it’s in the order of precedence. We will be using KUTTypeData since we want to send our item as type Data.
  4. The second method to conform to –  in this method you will convert the  object to the type identifier which in our case is KUTTypeData. So we will be converting the object to JSON.
  5. We are simply encoding the class properties to JSON using JSONEncoder(). The progress variable keeps track of the loading / conversion.
  6. As soon as the loading is complete, the completion hander closure is called and the converted data is passed.

Now lets conform to NSItemProviderReading:

// 1
static var readableTypeIdentifiersForItemProvider: [String] {
        return [(kUTTypeData) as String]
    }
// 2
    static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> PodcastModelData {
        let decoder = JSONDecoder()
        do {
            let myJSON = try decoder.decode(podcastModelData.self, from: data)
            return myJSON
        } catch {
            fatalError("Err")
        }
        
    }

Lets break down the above code:

  1. readableTypeIdentiferForItemProvider – again returning array of type identifiers in order of highest fidelity. In this case we are only returning KUTTypeData.
  2. This method creates a new instance of class with the given data and the identifier. In this method we will be using JSONDecoder() to decode the data back to instance of class (podcastModelData). The actual function returns ‘self’ however, it was giving me some issues so I added final infront of the class name and instead of ‘self‘ wrote the class name.

That’s it really! Now you it’s pretty straight forward to create UIDragItems with custom NSItemProvider.

func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
     
        let podcastItem = PodcastModelData(collectionName: collectionName, feedURL: feedUrl, artworkURL100: artworkUrl)
        
        let itemProvider = NSItemProvider(object: podcastItem)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        return [dragItem]
    }

The NSitemProvider constructor requires the object of the class and not the class itself. In this case I am giving it podcastItem. The drag item constructor requires the itemProvider which we created earlier.

Since I am dropping all these elements on a custom circleView, therefore I am using UIDropInteractionDelegate and using this method:

   func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
     session.loadObjects(ofClass: PodcastModelData.self) { (items) in
            if let podcasts = items as? [PodcastModelData] {
                //....
              //Do whatever you want to do with your dropped items here
            }
            
        }
      
    }

If you want to drop it on a table view then you have to use this function:

func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { 
...
}

 

You can get the full source code for this project on my github here. Also check out the app in action here on my Twitter.