Slide 1

Slide 1 text

See Swift C It’s been a sea of change for me! David Hoerl (dhoerl at mac dot com)

Slide 2

Slide 2 text

Swift Is Fantastic! Modern and Rich Functional programming idioms Elegant nil handling with optionals Code can be very explicit, or quite terse Imposes more structure than Objective C

Slide 3

Slide 3 text

Swift Is Fantastic! Modern and Rich Functional programming idioms Elegant nil handling with optionals Code can be very explicit, or quite terse Imposes more structure than Objective C But soooooo many blogs to read every week!

Slide 4

Slide 4 text

Swift Works Well With Both Objective C and C Construct a bridging header Virtually all Objective C code imports Xcode 6/7 support Objective C annotations: nullability, type and NS_REFINED_FOR_SWIFT Access a Raft of C functions: Darwin, Core Foundation, your functions

Slide 5

Slide 5 text

Reference “Using Swift with Cocoa and Objective-C” “Interacting With C APIs” Chapter Chart with mappings between C types and Swift Pointers and buffers

Slide 6

Slide 6 text

Swift “Switch” Statement Look similar to C C compilers typically generate a jump table for performance Think of Swift case statements as cascading “if” and “if else” - first ‘case’ is always evaluated Structure code for readability, rich case statements

Slide 7

Slide 7 text

Structs Like C structure with a suite of functions that operate on it Memory usage similar to C (rounds up to “stride()”) Protection from stupid errors: - contants and variables (constants set with init()) - mutating functions must be so marked - Protocols!

Slide 8

Slide 8 text

struct S { var a: Int32 = 0 var b: Int32 = 0 func total() -> Int32 { let c = a + b return c } } var s = S() s.a = 10 s.b = 1 print("Sum: \(s.total())") print("Sizeof(S): \(sizeof(S)) sizeOfValue(s): \(sizeofValue(s))") Sum: 11 Sizeof(S): 8 sizeOfValue(s): 8 Structs Not shown: “stride(s) gives you the memory usage within an array

Slide 9

Slide 9 text

Arrays Value types Typed, like C: “var foo: [S] = []” Memory usage similar to C Very rich API Copying does NOT mean memory duplication!

Slide 10

Slide 10 text

var sArray = [S](count: 1_000, repeatedValue: s) // tried other initializers, no change to size below print("SizeOfValue(sArray): \(sizeofValue(sArray))") // prints 8 // This will let the closure in the arg access the Array's contiguous storage through ubp: sArray.withUnsafeMutableBufferPointer { (inout ubp: UnsafeMutableBufferPointer) -> Void in print(ubp) // UnsafeBufferPointer(start: 0x0000000100809e20, length: 1000) let numElementsInBuffer = ubp.count // A pointer to the first and last element of the array's buffer: let firstElementBytePtr = UnsafePointer(ubp.baseAddress) let secondElementBytePtr = UnsafePointer(ubp.baseAddress.successor()) let lastElementBytePtr = UnsafePointer(ubp.baseAddress.advancedBy(numElementsInBuffer - 1)) let bufferElementStride = firstElementBytePtr.distanceTo(secondElementBytePtr) print("Stride in buffer: \(bufferElementStride)") // prints 16 let bufferSize = firstElementBytePtr.distanceTo(lastElementBytePtr) + bufferElementStride print("Size of buffer in bytes: \(bufferSize)") // prints 16000 } Advanced Arrays From https://forums.developer.apple.com/thread/8726

Slide 11

Slide 11 text

Pointers Mutating and non-mutating (similar to “const”) - UnsafePointer - UnsafeMutablePointer Pointers and “Buffer Pointers” - UnsafePointer equivalent to “const int32_t *p” - UnsafeBufferPointer equivalent to “const int32_t[size]”

Slide 12

Slide 12 text

More Pointers UnsafePointer: access via subscripts UnsafeBufferPointer: access via - subscripts (you can retrieve the bounds) - for byte in myBufferPointer { …

Slide 13

Slide 13 text

import Swift import Darwin //import Foundation do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) // CChar == Int8 ptr[0] = 72 ptr[1] = 111 ptr[2] = 119 ptr[3] = 100 ptr[4] = 105 ptr[5] = 101 ptr[6] = 33 if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Simple UnsafeMutablePointer

Slide 14

Slide 14 text

import Swift import Darwin //import Foundation do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) // CChar == Int8 ptr[0] = 72 ptr[1] = 111 ptr[2] = 119 ptr[3] = 100 ptr[4] = 105 ptr[5] = 101 ptr[6] = 33 if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Simple UnsafeMutablePointer

Slide 15

Slide 15 text

do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) for (i, c): (Int, Character) in "Howdie!".characters.enumerate() { ptr[i] = String(c).nulTerminatedUTF8.withUnsafeBufferPointer( { (p: UnsafeBufferPointer) -> CChar in return CChar(p[0]) } ) } if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Dissecting Strings

Slide 16

Slide 16 text

do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) for (i, c): (Int, Character) in "Howdie!".characters.enumerate() { ptr[i] = String(c).nulTerminatedUTF8.withUnsafeBufferPointer( { (p: UnsafeBufferPointer) -> CChar in return CChar(p[0]) } ) } if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Dissecting Strings

Slide 17

Slide 17 text

do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) for (i, c): (Int, Character) in "Howdie!".characters.enumerate() { ptr[i] = String(c).nulTerminatedUTF8.withUnsafeBufferPointer( { (p: UnsafeBufferPointer) -> CChar in return CChar(p[0]) } ) } if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Dissecting Strings

Slide 18

Slide 18 text

do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) for (i, c): (Int, Character) in "Howdie!".characters.enumerate() { ptr[i] = String(c).nulTerminatedUTF8.withUnsafeBufferPointer( { (p: UnsafeBufferPointer) -> CChar in return CChar(p[0]) } ) } if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Dissecting Strings

Slide 19

Slide 19 text

do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) for (i, c): (Int, Character) in "Howdie!".characters.enumerate() { ptr[i] = String(c).nulTerminatedUTF8.withUnsafeBufferPointer( { (p: UnsafeBufferPointer) -> CChar in return CChar(p[0]) } ) } if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Dissecting Strings

Slide 20

Slide 20 text

do { let ptr = UnsafeMutablePointer(calloc(7 + 1, 1)) for (i, c): (Int, Character) in "Howdie!".characters.enumerate() { ptr[i] = String(c).nulTerminatedUTF8.withUnsafeBufferPointer( { (p: UnsafeBufferPointer) -> CChar in return CChar(p[0]) } ) } if let newString = String.fromCString(ptr) { print(newString) } free(ptr) } Dissecting Strings

Slide 21

Slide 21 text

func hexToData0(str: NSString) -> NSData { let len = str.length/2 var data = NSMutableData(capacity:len)! var num: [Int8] = [ 0, 0, 0 ] let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding) for var i=0; i

Slide 22

Slide 22 text

- (NSData *)hexToData:(NSString *)str { const char *ptr = [str cStringUsingEncoding:NSASCIIStringEncoding]; NSUInteger len = [str length]/2; NSMutableData *data = [NSMutableData dataWithCapacity:len]; while(len--) { char num[3] = (char[]){ 0, 0, 0 }; num[0] = *ptr++; num[1] = *ptr++; uint8_t n = (uint8_t)strtol(num, NULL, 16); [data appendBytes:&n length:1]; } return data; } Simple C ➡ Swift http://stackoverflow.com/questions/26346542/how-to-translate-push-tokens-between-nsdata-and-nsstring-representations-in-swif/26346543 func hexToData0(str: NSString) -> NSData { let len = str.length/2 var data = NSMutableData(capacity:len)! var num: [Int8] = [ 0, 0, 0 ] let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding) for var i=0; i

Slide 23

Slide 23 text

- (NSData *)hexToData:(NSString *)str { const char *ptr = [str cStringUsingEncoding:NSASCIIStringEncoding]; NSUInteger len = [str length]/2; NSMutableData *data = [NSMutableData dataWithCapacity:len]; while(len--) { char num[3] = (char[]){ 0, 0, 0 }; num[0] = *ptr++; num[1] = *ptr++; uint8_t n = (uint8_t)strtol(num, NULL, 16); [data appendBytes:&n length:1]; } return data; } Simple C ➡ Swift http://stackoverflow.com/questions/26346542/how-to-translate-push-tokens-between-nsdata-and-nsstring-representations-in-swif/26346543 func hexToData0(str: NSString) -> NSData { let len = str.length/2 var data = NSMutableData(capacity:len)! var num: [Int8] = [ 0, 0, 0 ] let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding) for var i=0; i

Slide 24

Slide 24 text

- (NSData *)hexToData:(NSString *)str { const char *ptr = [str cStringUsingEncoding:NSASCIIStringEncoding]; NSUInteger len = [str length]/2; NSMutableData *data = [NSMutableData dataWithCapacity:len]; while(len--) { char num[3] = (char[]){ 0, 0, 0 }; num[0] = *ptr++; num[1] = *ptr++; uint8_t n = (uint8_t)strtol(num, NULL, 16); [data appendBytes:&n length:1]; } return data; } Simple C ➡ Swift http://stackoverflow.com/questions/26346542/how-to-translate-push-tokens-between-nsdata-and-nsstring-representations-in-swif/26346543 func hexToData0(str: NSString) -> NSData { let len = str.length/2 var data = NSMutableData(capacity:len)! var num: [Int8] = [ 0, 0, 0 ] let ptr = str.cStringUsingEncoding(NSUTF8StringEncoding) for var i=0; i

Slide 25

Slide 25 text

CSV Parsers CHCSVParser: read & write, huge suite of options
 https:/ /github.com/davedelong/CHCSVParser cCSVParse: small C function, returns a dictionary
 Original: http:/ /michael.stapelberg.de/cCSVParse/
 Supported: https:/ /github.com/JanX2/cCSVParse CSVParserInSwift
 https:/ /github.com/dhoerl/CSVParserInSwift

Slide 26

Slide 26 text

CSV Character Loop var textp, laststop, lineEnd: UnsafePointer while textp < lineEnd { switch textp[0] { case ASCII.BackSlash.rawValue: textp++ case ASCII.quote.rawValue: quoteCount++ case delimiter where quoteCount % 2 == 0: // There is a delimiter which is not between an unmatched pair of quotes? if textp > laststop { let s = parseStringFrom(laststop, to: textp) if !s.isEmpty { delegate?.csvParserDidReadField(s, atIndex: fieldNumber) } } ++fieldNumber laststop = textp + 1 default: break } // Go to the next character textp++ } const char *textp, *laststop, *lineEnd; while (textp < lineEnd) { switch(textp[0]) { case '\\': textp++; break; case '\"': quoteCount++; break; default: if(textp[0] == delimiter && (quoteCount % 2) == 0) { // There is a delimiter which is not between an unmachted pair of quotes? if(textp > laststop) { NSString *s = parseString(textp, laststop, encoding); if([s length] > 0 && respondsToDidReadField) { [delegate parser:self didReadField:s atIndex:fieldNumber]; } } ++fieldNumber; laststop = textp + 1; } } // Go to the next character textp++; }

Slide 27

Slide 27 text

CSV Character Loop const char *textp, *laststop, *lineEnd; while (textp < lineEnd) { switch(textp[0]) { case '\\': textp++; break; case '\"': quoteCount++; break; default: if(textp[0] == delimiter && (quoteCount % 2) == 0) { // There is a delimiter which is not between an unmachted pair of quotes? if(textp > laststop) { NSString *s = parseString(textp, laststop, encoding); if([s length] > 0 && respondsToDidReadField) { [delegate parser:self didReadField:s atIndex:fieldNumber]; } } ++fieldNumber; laststop = textp + 1; } } // Go to the next character textp++; } var textp, laststop, lineEnd: UnsafePointer while textp < lineEnd { switch textp[0] { case ASCII.BackSlash.rawValue: textp++ case ASCII.quote.rawValue: quoteCount++ case delimiter where quoteCount % 2 == 0: // There is a delimiter which is not between an unmatched pair of quotes? if textp > laststop { let s = parseStringFrom(laststop, to: textp) if !s.isEmpty { delegate?.csvParserDidReadField(s, atIndex: fieldNumber) } } ++fieldNumber laststop = textp + 1 default: break } // Go to the next character textp++ }

Slide 28

Slide 28 text

“But wait, there’s more” –Billy Mays

Slide 29

Slide 29 text

Comercial Plug: Dash

Slide 30

Slide 30 text

Comercial Plug: PopClip

Slide 31

Slide 31 text

My Favorite Swift Blogs Erica Sadun: http:/ /ericasadun.com
 (lots on Playgrounds, lively, this new mother never sleeps!) Airspeed Velocity: http:/ /airspeedvelocity.net
 (really high level, mind twisters) Natasha: http:/ /natashatherobot.com Jameson Quave: http:/ /jamesonquave.com/blog NSHipster: http:/ /nshipster.com (well known) Mike Ash: https:/ /www.mikeash.com/pyblog/ (well known)

Slide 32

Slide 32 text

Related Forum Posts Memory Layout: 
 https:/ /devforums.apple.com/thread/272013 Memory consumed by large arrays:
 https:/ /forums.developer.apple.com/thread/8726

Slide 33

Slide 33 text

WWDC 2015 “Protocol-Oriented Programming in Swift” –Be like Crusty