iOS

Swift

Swift Style Guide


// Optional binding - safe way to handle nils/optionals
let tempResult = json["main"]["temp"].double!
to
if let tempResult = json["main"]["temp"].double {}

// Strings
let name = "Rosa"
let greeting = "Welcome, \(name)!"
let longer = greeting + " We are happy!"

let m = 2
let msg = "\m times 2 is \(Double(m) * 2)"
let a = "String are value types"

let cafe1 = "Cafe\u{301}"
let cafe2 = "Café"
print(cafe1 == cafe2)

let truncated = String("abc".prefix(2))

// Arrays
let names = ["Anna", "Alex", "Brian"]
let numbers = [1, 2, 3]
var emptyDoubles: [Double] = []
var emptyFloats: Array = Array() // or

// Dictionary
var emptyDict: [String: String] = [:]
let params : [String: String] = ["lat" : "1", "lon" : "2"]
var responseMessages = [200: "OK",
                        403: "Access forbidden",
                        404: "File not found",
                        500: "Internal server error"]
print(responseMessages[200])

for (key, value) in dict {
   print(key, value)
}

let imagePaths = ["star": "star.png",
                  "portrait": "portrait.jpg",
                  "spacer": "spacer.gif"]

for (name, path) in imagePaths {
    print("The path to '\(name)' is '\(path)'.")
}

// Conversions
String(double) or text = "\(weatherDataModel.temperature)°"
Int(double)

// Special chars
// control + command + spacebar (degree)

// Loops
for name in names[2...] {

}

/////////// Structs
struct Resolution {
   var width = 0
   var height = 0
}

let vga = Resolution(width: 640, height: 480) // auto initializer

struct Celsius {
   var tempCelcius: Double
   init(fromFahrenheit fahrenheit: Double) {
      tempCelcius = (fahrenheit - 32.0) / 18
   }
   init(_ calcius: Double) {
      tempCelcius = celsius
}

let boiling = Celcius(fromFahrenheit: 221.0)

// function -> does not need to be on object
// method -> must be on class

// Parameter names to initializers
struct Color {
   let red, green, blue: Double
   init(red: Double, green: Double, blue: Double) {
      self.red = red
      ...
   }
}


///////// Classes
class Category {
    var name: String = ""
    var color: String = ""
}

var categories : Array?

class VideoMode { // no auto initializer - boo!
   var resolution = Resolution()
   var interlaced = false
   var name: String?
}

// - Since classes are reference types
// === -> refers to same class reference
// ==  -> compares values (not instance)

///////// Enums

enum CompassPoint {
   case north
   case south
   case east
   case west
}

var direction = CompasPoint.west
direction = .east // can do this once already initialized

switch direction {
   case .north:
      print("Heading north!"
   default: 
      print("Not safe!")
   ...
}

enum Planet { 
   case mercury, venus, mars
}

enum ASCIIChars: Character { // Raw values
   case tab = "\t"
   case lineFeed = "\n"
}

// give enumeration types singular names rather than plural for readabilty
// Foundation


/////////// Functions

func sayHello() -> String {
   return "Hello!"
}

print(sayHello())

func greet(person: String, alreadyGreeted: Bool) -> String {
   if alreadyGreeted {
      return greetAgain(person: person)
   } else {
      return greet(person: person)
   }
}
print(greet(person: "Tim", alreadyGreeeted: true))

func greet(person: String) {
 // no return value - actually there is - it's type Void which is an empty tuple with is written as ()
}

// Funcs with multipe return types
func minMax(array: [Int]) -> (min: Int, max: Int) {
   ...
   return (currentMain, currentMax) // tuple
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max \(bounds.max))

// Function argument labels and Parameter names
// - each function has both an argument label and a parameter name
// - argument label used when calling the func
// - parameter name is used in the implementation
// - by default, parameters use their parameter names as argument label

// Parameter names
func someFunc(firstParameterName: Int, secondParameterName: Int) {

}
someFun(firstParameterName: 1, secondParemeterName: 2)

// Argument labels
func someFunc(argumentLabel parameterName: Int) {

}

i.e.

func greet(person: String, from hometown: String) -> String {
   return "Hello \(person)! Glad visit from \(hometown)."
}

// Use of function argument labels can allow a function to be called expressively
// While still providing function body that is readable and clear in intent

// If no want argument label use _
func someFunc(_ firstParameterName: Int, secondParameterName: Int) {
}
someFunc(1, secondParameterName: 2)

// Variadic Parameters
// - takes 0 or more values
// - can only have one per function

func mean(_ numbers: Double...) -> Double {
}
mean(1, 2, 3)
mean(4, 5, 6, 7)

// Numbers
struct Int
struct Double
struct Flot
struct Decimal
class NumberFormatter

// Collections
struct Array
struct Dictionary
struct Set

// Nil-Coalescing Operator
let defaultColor = "red"
let userColor = String? // defaults to nil

var colorName = userColor ?? defaultColor
/* userColor is nil, so colorName is set to default "red" */

// typealias - abbreviated named alias
public class LinkedListNode {
public class LinkedList {
  public typealias Node = LinkedListNode

/////// Misc
enum Result { case success(T), error(Error) }

Protocols and delegates

This is how we pass data back from one viewController to another.
Here we send data back to Weather from ChangeCity via a protocol.

Protocol

import UIKit

// Method others must implement
protocol ChangeCityDelegate {
    func userEnteredANewCityNew(city: String)
}

class ChangeCityViewController: UIViewController {

   var delegate : ChangeCityDelegate? // optional

   // At some point call our delegate
   @IBAction func getWeatherPressed(_ sender: AnyObject) {
        
        // If we have a delegate set, call the method userEnteredANewCityName
        delegate?.userEnteredANewCityNew(city: "Calgary") // optional chaining
        
    }
}

Delegate

import UIKit

class WeatherViewController: ChangeCityDelegate {

    // Set yourself as delegate
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "changeCityName") {
            let destinationVC = segue.destination as! ChangeCityViewController
            destinationVC.delegate = self
        }
    }

    // Write the Delegate method here:
    func userEnteredANewCityNew(city: String) {
        print(city)
    }
}

Guard clauses

guard let url = URL(string: string) else {
    return
}

guard var node = head else {
 return nil
}
 
guard let account = context.selectedAccount else { fatalError("attempt to pay bill w/o an account") }

Misc

Cocopods

Needs a higher version of ruby. So remember to switch to the correct version using rvm

rvm 2.3.3
pod init
vi Podfile
pod install
pod update

Swift Playground

// For best results, don’t forget to select “Show Rendered Markup” from XCode’s “Editor” menu

How to set device to different locales

On device Settings > General > International

Objective-C

Static properties
header.h

extern NSString *const kStartKey;
extern NSString *const kEndKey;

body.m

NSString *const kStartKey = @"start";
NSString *const kEndKey = @"end";

Cmd + Shift + Right Click to select subviews in storyboard
Cmd + Option + = to re-layout elements autolayout
Shift + Right Click Select subviews in storyboard

Simple initializer

- (instancetype)init
{
    self = [super init];
    if (self) {
        // do init work here, e.g. _myIvar = someParam;
    }
    return self;
}
NS_ASSUME_NONNULL_BEGIN

@interface Foo : NSObject 

- (instancetype)initWithBar:(Bar *)client NS_DESIGNATED_INITIALIZER;

#pragma mark Unavailable Initializers
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END

Protocols

@protocol PlayerStateDelegate 
- (void)playerStateDidChange:(id)playerState;
@end

@property (nonatomic, weak) id delegate;

Tools

Image compression
Network latency

Design sizes

https://designcode.io/iosdesign-guidelines
http://ivomynttinen.com/blog/the-ios-7-design-cheat-sheet

Misc

NSLog(@"%s #%d: Error fetching access token with error:%@", __FILE__, __LINE__, error);
NSLog(@"%@", @(__FUNCTION__));

Speed up build by putting this is ~/.bashrc

export USE_CCACHE=1

How to see who calls what method

Screen Shot 2017-07-12 at 2.47.31 PM.png

Playgrounds not working

File -> Close "Name.playground"
File -> Close Playground
Quit Xcode
Re-open Xcode
Advertisements

5 Comments (+add yours?)

  1. Jody
    Oct 10, 2012 @ 23:26:44

    Something that always bothered me about Apple’s APIs, or at least examples of their usage, is the messyness of implementation. Is it lack of OO design?

    i.e. The table view delegate from above implements the cellForRowAtIndex, and this one method is responsible for dequeueing or creating a cell (factory) as well as populating it (builder/strategy?)

    Reply

    • JR
      Oct 11, 2012 @ 19:12:48

      I’ve heard arguments both ways.

      Some people I know love the API. They think it’s one of the most mature, stable platforms they’ve ever worked on.

      Others have thoughts similar to you. They think certain abstractions leak responsibility and are messy from an OO point-of-view.

      I personally like the API. But I would be the first to agree it isn’t perfect (the ALAssetLibrary I find particularly cumbersom).

      Thanks for the comment Jody.

      Reply

  2. rob v
    Jan 03, 2013 @ 02:24:51

    some of your examples would be great to add into the code snippets library in the XCode inspector panel as user snippet, even if temporarily, until they become familiar. thanks for posting

    Reply

  3. chandresh maurya
    Jun 11, 2014 @ 17:24:17

    how to use nsmutablearray to add multiple images in a single use of cell

    Reply

  4. chandresh maurya
    Jun 11, 2014 @ 17:25:26

    how to use Ns mutable array to add multiple images in a single row of cell for ios

    Reply

Leave a Reply to chandresh maurya Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: