Tag: iOS-Coding

11 Posts Found
 

Swift Dictionary Extension to Create a URL Query String

Posted: 9/27/2016 1:02 PM

One of the more common parts of web-based client/server app architecture is converting groups of strings into URL-encoded values that can be included in a URL or form data. It's a tedious process, and I've found the easiest approach to take is put all of my URL or form variables into a dictionary and then call a function on that dictionary to convert it to a URL query string. I've encapsulated this logic into an extension for the Dictionary type.

It requires my String URL-Encoding Extension that I've previously posted.

You can find the source for my extension on Github

 

Swift String Extension for URL Encoding

Posted: 9/26/2016 4:58 PM

Here's a convenience String extension that will return a URL-encoded string based on the current string.

You can find the code for my extension on Github

 

UIView Extension Finds First Responder in Subviews

Posted: 9/25/2016 1:38 PM

Often times when you have some kind of a "Done" button in your view controller, you'll have logic where you want to resign the first responder. There are a few different approaches to this, such as (for a UITextField) using the UITextFieldDelegate textFieldShouldBeginEditing(UITextField) function to keep track of the current first responder in a global variable, then sending a resignFirstResponder() message to that variable.

An easier approach which doesn't involve any bookkeeping for tracking the first responder is this UIView extension which will traverse all of the subviews (and their subviews) in a given UIView, looking for the first responder and optionally resigning it.

To use it, you just call myView.findFirstResponder() or myView.findAndResignFirstResponder(), to either find and return the first responder, or find and resign the first responder, respectively.

You can find the code for my extension on Github

 

iOS App Version Utility Class

Posted: 9/21/2016 6:09 PM

My iOS app version numbers conform to the format "1.2.3 (1004)", where "1" is the major version, "2" is the minor version, "3" is the patch version, and "1004" is the overall build number. "1.2.3" is a single "Version" text field in Xcode, while "1004" is a single "Build" text field in Xcode.

To make working with app version numbers easier, I've created a utility class that reads the version strings from the info.plist and splits it into values that conform the description that I listed about. It also creates a friendlier formatted string of the version info that you can display in your app.

You can find the source for this class on Github

 

New iPhone App: BlackBook+

Posted: 8/21/2016 3:28 PM

I'm proud to introduce my first major iOS app, BlackBook+. It's currently available for free in the iOS App Store, and is written almost completely in Swift.

 

How About a Cleaner Swift Selector Syntax

Posted: 8/17/2016 6:45 PM

Newer versions of Swift introduced the Selector convention #selector(ClassName.FunctionName()) to replace the old-style Objective C style Selector conventions.

    func makeButton() {
        let button = UIButton(type: .System)
        button.setTitle("Test Button", forState: .Normal)
        button.addTarget(self, action: #selector(MyViewController.didTapButton(_:)), forControlEvents: .TouchUpInside)
    }

    func makeOtherButton() {
        let button = UIButton(type: .System)
        button.setTitle("Test Other Button", forState: .Normal)
        button.addTarget(self, action: #selector(MyViewController.didTapOtherButton(_:)), forControlEvents: .TouchUpInside)
    }

This is kind of ugly though, having your Selectors scattered all throughout your code.

Instead, you can create a private Extension of the Selector class, with a single static variable for each Selector. This way, you can keep all of your Selectors local in one place, neatly organized. Your code reads much cleaner, and since Xcode knows that the UIButton.addTarget() function takes a Selector as its second argument, you can leave off the Selector class name.

    func makeButton() {
        let button = UIButton(type: .System)
        button.setTitle("Test Button", forState: .Normal)
        button.addTarget(self, action: .DidTapButton, forControlEvents: .TouchUpInside)
    }

    func makeOtherButton() {
        let button = UIButton(type: .System)
        button.setTitle("Test Other Button", forState: .Normal)
        button.addTarget(self, action: .DidTapOtherButton, forControlEvents: .TouchUpInside)
    }

    private extension Selector {
        static let DidTapButton = #selector(MyViewController.didTapButton(_:))
        static let DidTapOtherButton = #selector(MyViewController.didTapOtherButton(_:))
    }
 

Swift-Native Method to Test If a Local NSURL is a File or a Directory

Posted: 4/7/2016 8:33 PM

As of this writing, NSFileManager unfortunately doesn't have a Swift-native way of determining if the object at an NSURL is a file or a directory. You can call the NSFileManager fileExistsAtPath:isDirectory: function, but the isDirectory parameter takes a reference to an Objective-C boolean, NOT a Swift-native boolean.

Extensions to the rescue! We can encapsulate our directory-testing logic into an NSFileManager extension that returns a Swift-native Bool value, so we don't have to play with any Objective-C in our code.

    //
    //  NSFileManager+CKIsDirectory.swift
    //

    import Foundation


    extension NSFileManager {

        func isDirectoryAtPath(url: NSURL) -> Bool {
            // we need an Objective-C boolean
            var isDirectory: ObjCBool = ObjCBool(false)

            // determine if this is a directory
            self.fileExistsAtPath(url.relativePath!, isDirectory: &isDirectory)

            // convert to a Swift Boolean
            let isDirectoryBool = Bool(isDirectory)

            // return the Swift boolean
            return isDirectoryBool
        }

    }
 

UIColor Creation w/ Hex Values

Posted: 4/2/2016 7:02 PM

As a web developer by day, my world revolves around the 6 character hexadecimal color codes that we use on web pages. For example, #FF0000 is the reddest of the reds.

Unfortunately, UIColor doesn't support a hexadecimal constructor, only CGFloat red/green/blue values. So extensions to the rescue!

Below you can find an extension to UIColor that takes a hexadecimal value as its color and creates an appropriate UIColor object: let color = UIColor(hex: "1289AB")

Note that it requires the Swift extension from my previous article about Swift substrings.

    //
    //  UIColor+CKHexColors.swift
    //

    import Foundation
    import UIKit


    extension UIColor {


        // constructor takes a hex color as a string in the format: "1289AB"
        convenience init(hexColor: String) {
            let redColor = UIColor.hexColorToFloat(hexColor[0...1])
            let greenColor = UIColor.hexColorToFloat(hexColor[2...3])
            let blueColor = UIColor.hexColorToFloat(hexColor[4...5])

            self.init(red: redColor, green: greenColor, blue: blueColor, alpha: 1.0)
        }



        // converts a hex color string to a float number
        private class func hexColorToFloat(hexColor: String) -> CGFloat {
            let char0 = hexColor[0...0].uppercaseString
            let char1 = hexColor[1...1].uppercaseString

            let value0 = UIColor.hexToInt(char0)
            let value1 = UIColor.hexToInt(char1)

            let colorValue = (value0 * 16) + value1

            let floatValue: CGFloat = CGFloat(colorValue) / 255.0

            return floatValue
        }


        // converts a hex character to an integer
        private class func hexToInt(hex: String) -> Int {
            var intValue = 0

            switch hex {
                case "A":
                    intValue = 10
                case "B":
                    intValue = 11
                case "C":
                    intValue = 12
                case "D":
                    intValue = 13
                case "E":
                    intValue = 14
                case "F":
                    intValue = 15
                default:
                    intValue = Int(hex) ?? 0
            }

            return intValue
        }


    }
 

Swift String Substring Retrieval

Posted: 3/30/2016 2:23 PM

Swift supports some pretty cool subscript operations, particularly in for loops. But what about String manipulation? Extensions to the rescue!

Here you can find a Swift extension that lets you specify ranges when working with String objects to obtain substrings:

    let string1 = "ABCDE"
    let string2 = string1[0...3] // returns "ABCD"
    let string3 = string1[1..<4] // returns "BCD"

These are valid String objects that can be used as you would any other String.

    //
    //  String+CKTextManipulation.swift
    //

    import Foundation


    extension String {


        subscript (i: Int) -> Character {
            return self[self.startIndex.advancedBy(i)]
        }

        subscript (i: Int) -> String {
            return String(self[i] as Character)
        }

        subscript (r: Range<Int>) -> String {
            let start = self.startIndex.advancedBy(r.startIndex)
            let end = self.start.advancedBy(r.endIndex - r.startIndex)

            return self[start..<end]
        }

    }
 

Set the Fill Color for a UIView

Posted: 3/19/2016 9:49 PM

On a UIView, you're able to set the backgroundColor property to change the background color of the view. This works, most of the time.

Unfortunately, when you change the background color when the view is loaded in a UITableViewCell, the background color disappears when the table cell is selected. The solution is to create a subclass of UIView and override the drawRect() function to manually draw a fill color into the view bounds.

When you reset the fill color, the call to self.setNeedsDisplay() tells the UIView to redraw itself with the new color.

    //
    //  CKFillView.swift
    //


    class CKFillView: UIView {

        private var _fillColor = UIColor.whiteColor()

        // set this variable to the color that you want to fill
        var fillColor: UIColor {
            get {
                return self._fillColor
            }
            set {
                if (self._fillColor != newValue) {
                    self._fillColor = newValue
                    self.setNeedsDisplay()
                }
            }
        }

        // draw the entire rect with the fill color
        override func drawRect(rect: CGRect) {
            let context = UIGraphicsGetCurrentContext()

            let colorComponents = CGColorGetComponents(self.fillColor.CGColor)
            let red = colorComponents[0]
            let green = colorComponents[1]
            let blue = colorComponents[2]
            let alpha = CGColorGetAlpha(self.fillColor.CGColor)

            CGContextSetRGBFillColor(context, red, green, blue, alpha)

            CGContextFillRect(context, rect)

            super.drawRect(rect)
        }

    }
 

UIImage Scaling Extension

Posted: 3/15/2016 7:36 PM

The iPhone app I'm working on in my spare time lets the user capture photos as part of its functionality. After I receive the image, I need to resize it so that it's a thumbnail size.

To make this easier, I've written a UIImage Swift extension that provides you two functions: scaleToMaxSize() scales an image to the maximum size specified, scaleToSize() scales the image to exactly the specified size. scaleToMaxSize() works in conjunction with scaleToSize().

    //
    //  UIImage+CKScaling.swift
    //  BlackBook
    //
    //  Created by Corey Klass on 2/28/16.
    //  Copyright © 2016 Corey Klass. All rights reserved.
    //

    import Foundation
    import UIKit


    extension UIImage {


        func scaleToMaxSize(maxSize: CGSize) -> UIImage {
            // get the scale values for the width and height
            let xScale = maxSize.width / self.size.width
            let yScale = maxSize.height / self.size.height

            // we'll need one of these scales, whichever fits
            let xScaleSize = CGSizeMake(self.size.width * xScale, self.size.height * xScale)
            let yScaleSize = CGSizeMake(self.size.width * yScale, self.size.height * yScale)

            var newSize: CGSize

            // if the x scale is too large, use the y scale
            if ((xScaleSize.width > maxSize.width) || (xScaleSize.height > maxSize.height)) {
                newSize = yScaleSize
            }

            // otherwise use the x scale
            else {
                newSize = xScaleSize
            }

            // resize and return the image
            let image = self.scaleToSize(newSize)

            return image
        }



        func scaleToSize(size: CGSize) -> UIImage {
            // Create a bitmap graphics context
            // This will also set it as the current context
            UIGraphicsBeginImageContext(size)

            // Draw the scaled image in the current context
            self.drawInRect(CGRectMake(0.0, 0.0, size.width, size.height))

            // Create a new image from current context
            let scaledImage = UIGraphicsGetImageFromCurrentImageContext()

            // Pop the current context from the stack
            UIGraphicsEndImageContext()

            // Return our new scaled image
            return scaledImage
        }



    }