Skip to main content

Posts

Showing posts from August, 2014

Unsafe pointers in Swift: Conversion to and from a COpaquePointer (and CFunctionPointer) (Part II, Xcode 6 Beta 6; update Swift 3, Xcode 8)

The unsafe pointers in Swift posts, of which this is the second, are a tentative toe-dipping into the world of connecting Swift with the C functions provided in Apple's Darwin -> C -> stdlib header file. As such, this post is neither exhaustive nor expert, I am simply trying to fill a void where I find little else to work with in my experimentations.

You should read the code found here as if it were written in someone's personal notebook and never use it without first understanding it and satisfying yourself that it works correctly.
COpaquePointer With all of this in mind, here is my code for today, fulfilling the conversion of an UnsafeMutablePointer to and from a COpaquePointer:
let str = "Hello, pointer" let ps = UnsafeMutablePointer<String>.alloc(1) // allocate memory for one String instance ps.initialize(str) // intialize with a value let cps = COpaquePointer(ps) // convert UnsafeMutablePointer to COpaquePointer let nps = UnsafeMutablePointer<Str…

Unsafe pointers in Swift: A first look (Part I, Xcode 6 Beta 6; updated Swift 3, Xcode 8)

Let's suppose I want to alter an existing colour in some way, and that I decide to do this by taking the original hue, saturation and brightness values of the colour before increasing (or decreasing them).
var col = UIColor(hue: 0.4, saturation: 0.3, brightness: 0.7, alpha: 1.0) Having established a colour, I discover that there is a getHue() method for instances of a UIColor, which is perfect for the task of capturing colour values. But as soon as I start writing the get hue method in Swift, I'm hit with all these unsafe pointer things:
col.getHue(hue: UnsafeMutablePointer<CGFloat>, saturation: UnsafeMutablePointer<CGFloat>, brightness: UnsafeMutablePointer<CGFloat>, alpha: UnsafeMutablePointer<CGFloat>) While I might understand that a CGFloat is a type of float and that the pointer must be pointing at that float, it doesn't mean I know how to provide the information the parameters are demanding. And I am also a bit scared by the repeated use of th…

Swift: It's all in the protocols (Part III)

In the previous part of this series, I created a PartyPerson protocol and constructed classes around this. And here's the same protocol and classes with some minor tinkering:
protocol PartyPerson: class { var numberOfItemsOnYourPlate:Int {get} var name:String {get set} var isDrunk:Bool {get set} func tellUsABitAboutYourself() -> String func areYouDrunk() -> Bool func whatIsYourName() -> String } class YoungSocialite:PartyPerson { let food:[String] var numberOfItemsOnYourPlate:Int { return food.count } var isDrunk:Bool var name:String init (units:Int, name:String, food:[String]) { isDrunk = units > 3 ? true : false self.name = name self.food = food } func tellUsABitAboutYourself() -> String { return "OMG, I go out like twice every night. OMG, I know you. OMG. What a party. What a party. OMG." } func areYouDrunk() -> Bool { return isDrunk …

Swift: Multiple protocols in generic functions and elsewhere

Swift's algorithms typically restrict themselves to a single protocol for each generic type they employ. It is possible, however, to use more than one protocol inside your own generic functions, if you wish. But you must use the following syntax to do so:
func multiProtocol<T:protocol<MutableCollectionType, Printable>>(t:T) { } It is the keyword protocol that does the magic along with its angle brackets. These brackets enable the grouping together of protocols.
Going further Looking at other scenarios, where a generic syntax isn't employed, it is also possible to substitute a Protocol where we'd normally place a Type and to do so in the multiple style outlined above. But we cannot in these instances use Swift protocols that have references to self within their methods. This means in short that this wouldn't work:
func multiProtocol(t:protocol<MutableCollectionType, Printable>) { } // error But if we were to require Printable and BooleanType, this w…

Swift: AnyObject is not your only option for mixing things up ('Collections of Protocol Types')

There is a choice when creating arrays. We are encouraged to strongly type them (i.e. use a single type) but when needed use the AnyObject protocol (and also Any) to mix types.
[Equatable]() // error [SequenceType]() // error [SignedIntegerType]() // error Outside of generic functions, Swift's own protocols are not typically used in place of types. Although there are exceptions. For example BooleanType, Printable (and of course AnyObject itself):
var bol = [BooleanType]() // OK bol.append(true) // OK The rule appears to be that protocols which require a reference to self in their methods (or in the methods of protocols they adopt) are not able to be used as the basis for restriction of types in arrays.

Note: NSArray and NSMutableArray are at our disposal as well, but I'm focusing on Swift types here rather than Cocoa classes.
Roll your own protocol There is a way around this all or nothing approach, however, by making your own protocol and having certain types adopt it.
pro…

Swift generics: It's all in the protocols (Part II)

Forge your own fashion Generics aren't all about deciphering which hat goes with which dress. The great thing about Swift is that you can make your own outfits from scratch whenever you feel like it.

So let's decide a week or two ahead of the party to make our own set of rules (a protocol).
protocol PartyPerson { func tellUsABitAboutYourself() -> String var numberOfItemsOnYourPlate:Int {get} var isDrunk:Bool {get set} }   Power to the people And closer the time we can manufacture a couple of people along the lines of these PartyPerson etiquette rules:
class YoungSocialite:PartyPerson { var food:[String] var numberOfItemsOnYourPlate:Int { return food.count } var isDrunk:Bool init (units:Int, food:[String]) { self.food = food isDrunk = units > 3 ? true : false } func tellUsABitAboutYourself() -> String { return "OMG, I go out like twice every night. OMG, I know. OMG. What a party. W…

Swift generics: It's all in the protocols (Part I)

To begin writing a generic function, first of all you need to decide on the range of types that you'd like to invite to your party. And since we want to be as inclusive as possible, why not go crazy and invite all the members of Hashable?
struct Bool struct CFunctionPointer struct COpaquePointer struct Double struct Float struct Float80 struct Int struct Int8 struct Int16 struct Int32 struct Int64 struct ObjectIdentifier struct String struct UInt struct UInt8 struct UInt16 struct UInt32 struct UInt64 struct UnicodeScalar struct UnsafePointer Problem is, once they're inside the party there's very little we can do to entertain them:
func ha<T: Hashable>(t:T, b:T) { t.hashValue t == b } This is because Hashable only requires that adoptees employ the hashValue property, and Equatable (the only protocol that Hashable adopts) only requires == to be employed.
Your name's not down... If we choose something a bit more exclusive, like FloatingPointType then our …

Swift: Bytes for Beginners (Part IV)

In the documentation, Apple explains the numbers that a byte array generated from a utf8, utf16 or unicode scalar would contain. It also, in the advanced section, explains that we can directly input binary numbers.

In my view, this is no small step for those unacquainted with byte arrays and binary numbers, so this post aims to provide a small bridge between these two parts of the documentation as a helping hand to anyone who needs it.
8-bit binary number We enter a binary number into Xcode using the 0b prefix. So try this now. Write a 0b with any number of zeroes and ones after it in a playground file.
0b00000000000000000000000010101010 // returns 170 Next delete any number of zeroes after the "b" but before the first 1.
0b10101010 // returns 170 The number remains the same, those zeroes turned out to be unnecessary padding, but delete a one or change it to zero and your result changes.

Now let's try assigning a binary number to a UInt8:
let int:UInt8 = 0b00000000…

Swift: Bytes for Beginners (Part III)

Beyond UTF8 UTF8 is fine for regular text, but when special characters are inserted into a string then a character can span more than one byte. And if we are mixing up arrays then we might find that those special characters, for example emoji, are no longer held together and we end up with placeholders or nil being returned.
UTF16 Encoding We could at this point jump forward to the most flexible encoding (Unicode Scalar Representation), but for completeness I'm going to include the transformation of a UTF16 string, because while it doesn't solve the special character problem, it might be selected as a format for other reasons.
let str = "Hello, playground" var buff = [UInt16](str.utf16) var revbuff = reverse(buff) // You now have a buffer loaded with bytes!! if let aStr = String.stringWithBytesNoCopy(&revbuff, length:revbuff.count*sizeof(UInt16), encoding: NSUTF16LittleEndianStringEncoding, freeWhenDone:false) { aStr // returns "dnuorgyalp ,olleH"…

Swift: Bytes for Beginners (Part II)

Last time a string was converted into bytes and then transformed from bytes back into a string. Following on from this, I'm going to start by creating two separate byte arrays:
let strA = "Hello, " var buffA = [UInt8](strA.utf8) let strB = "playground" var buffB = [UInt8](strB.utf8) Note: I've simplified the construction of the byte arrays (aka buffers) since the last post and created them all on one line. This is thanks to reading this StackOverflow post.
Joining byte arrays together Now I'm simply going to join the two byte arrays together.
buffA += buffB And the same as last time transform this back into a string.
if let a = String.stringWithBytes(buffA, encoding: NSUTF8StringEncoding) { a // returns "Hello, playground" } Reversing a byte array As you can see the byte array is being treated like any other array. Now let's take this a step further and use one of Swift's algorithms to manipulate the array:
buffA = reverse(buff…

Swift: Bytes for Beginners (Part I)

Talk of buffers and bytes can be quite daunting and before you know it people are wanting you to XOR. But the code that I'm going to post in this series is going to move slowly. First of all we're going to start with a string:
var str = "Hello, playground" You should be comfortable with this first of all. Next we're going to create a buffer. Don't run away. A buffer is simply an array. And our buffer is going to be an array of unsigned 8-bit integers:
var buff = [UInt8]() Why unsigned 8-bit ints? Well these are the code units that a UTF8-encoded string works with. So that's the only thing we can use for this example.

But how do we know the string is UTF8-encoded? It isn't yet, but we're going to extract the utf8 bytes and then append them to our buffer (array) like this:
buff += str.utf8 Painless. Next let's transform those bytes back into a string for completeness:
String.stringWithBytes(buff, encoding: NSUTF8StringEncoding) A String (or r…

Pure Swift: Conversion of Cocoa dependent code (Xcode 6 Beta 5)

Original methods (using Cocoa) A week or so ago, I wrote a series of methods for a Gist String extension fork that simply borrowed unthinkingly from the Cocoa Framework:
extension String { func splitStringByCharacters() -> [String] { var arr = [String]() self.enumerateSubstringsInRange(Range(start: self.startIndex, end: self.endIndex), options: NSStringEnumerationOptions.ByComposedCharacterSequences, { (substring, substringRange, enclosingRange, bool) -> () in arr.append(substring)}) return arr } func splitStringBySentences() -> [String] { var arr = [String]() self.enumerateSubstringsInRange(Range(start: self.startIndex, end: self.endIndex), options: NSStringEnumerationOptions.BySentences, { (substring, substringRange, enclosingRange, bool) -> () in arr.append(substring)}) return arr } func splitStringByLines() -> [String] { var arr = [String]() self.enumerateSubstringsInRange(Range(start: self.…

Pure Swift: A little deeper into generics (Xcode 6 Beta 5 and Beta 6)

At the end of the last blogpost I delivered myself a challenge to write a method that could remove duplicates from a String or an Array of any type. And here's progress so far. I'm half way and I'm not sure how much further I can continue without some serious brainwork.

This is what I have:
func identifyDuplicates<seq: SequenceType where seq.Generator.Element: Equatable>(s:seq, contains:(seq, seq.Generator.Element, Int) -> Bool) -> [Int] { var sequence = s var indArr = [Int]() var i = 0 for a in sequence { if contains(sequence,a,i) { indArr.append(i) } i++ } return indArr } This generic method can take an array or a string and can be called respectively:
let dupArr = identifyDuplicates([1,2,2,3,4,3,4,4], { (a:[Int], b:Int, c:Int) -> Bool in contains(prefix(a, c),b)}) var str = "Hello, playground" let dupStr = identifyDuplicates(str, {(a:String, b:Character, c:Int) in contains(pr…

Pure Swift: My First Generic Method (Xcode 6 Beta 5)

I was thinking about how to transform an Array instance into a Set, where duplicates are removed. And to do this for an Int array was fairly straightforward,
func removeDuplicates(array:[Int]) -> [Int] { var arr = array var indArr = [Int]() var tempArr = arr var i = 0 for a in enumerate(arr) { if contains(prefix(arr, a.index), a.element) { indArr.append(a.index) } i++ } var ind = 0 for i in indArr { arr.removeAtIndex(i-ind) ind++ } return arr } but I didn't want to write a new method for every type of Array. I therefore took advantage of generics to write a method that took an Array of items that adopt the Comparable protocol, because that's exactly what we're doing to find duplicates; we're comparing the values of the items to one another.
func removeDuplicates<T: Comparable>(array:[T]) -> [T] { var arr = array var indArr = [Int…

Pure Swift: A one-line method to add insert functionality to String instances (Xcode 6.3; update for Xcode 7, iOS 9)

This is the third blogpost focusing on writing pure swift methods and extensions. And here's a really simple one to add insert functionality to String instances:
extension String { func insert(string:String,ind:Int) -> String { return prefix(self,ind) + string + suffix(self,count(self)-ind) } } "Hello World!".insert("Swift ", ind: 6) Enjoy!

Update: 14 April 2015 I wrote this post in the early days of Swift and in fact there's a much easier way of inserting a string called splice().
var aString = "Hello World!" aString.splice("Swift ", atIndex: advance(str.startIndex,6)) So while there are any number of ways that we can approach the insertion of a String without splice, for example using subscripting (inspired by a StackOverflow post):
extension String { mutating func insert(str:String, atIndex:String.Index) { self = self[Range(start: self.startIndex,end: atIndex)] + str + self[Range(start: atIndex,end:…

Pure Swift: A method for replacing occurrences of a string within a string (updated for Xcode 6.3.1, Swift 1.2 and Xcode 7 beta 1, Swift 2)

rangesOfString In the last blogpost, I created an extension to the String type to add a rangesOfString: method that was written purely in Swift.
extension String { func rangesOfString(findStr:String) -> [Range<String.Index>] { var arr = [Range<String.Index>]() var startInd = self.startIndex // check first that the first character of search string exists if contains(self, first(findStr)!) { // if so set this as the place to start searching startInd = find(self,first(findStr)!)! } else { // if not return empty array return arr } var i = distance(self.startIndex, startInd) while i<=count(self)-count(findStr) { if self[advance(self.startIndex, i)..<advance(self.startIndex, i+count(findStr))] == findStr { arr.append(Range(start:advance(self.startIndex, i),end:advance(self.startIndex, i+count(findStr)))) …

Swift: A pure Swift method for returning ranges of a String instance (updated for Xcode 6.3.1, Swift 1.2, Xcode 7, Swift 2 and Xcode 8.0, Swift 3)

A selection of algorithms that work with Strings Often familiarity makes us turn back to the Cocoa Framework, but Swift has a wealth of algorithms that we can use with String. These include:
distance(str.startIndex, str.endIndex) // string length count(str) // string length str[advance(str.startIndex, 4)] // get character at index 4 str[advance(str.startIndex, 4)...advance(str.startIndex, 8)] // get characters in range index 4 to 8 last(str) // retrieve last letter first(str) // retrieve first letter dropFirst(str) // remove first letter dropLast(str) // remove last letter filter(str, {!contains("aeiou", $0)}) // remove vowels indices(str) // retrieve the Range value for string isEmpty(str) // test whether there is anything in the string minElement(indices(str)) // first index str.substringToIndex(advance(minElement(indices(str)), 5)) // returns string up to the 5th character str.substringFromIndex(advance(minElement(indices(str)), 5)) // returns string from the 5th c…

Swift: Creating styled and attributed text with NSAttributedString and NSParagraphStyle (updated)

Note: Code has been updated following changes to UIFont in Xcode (6.1).

Cut and paste this code into your viewDidLoad. Run in the iOS Simulator on an iPhone (to see full effect of paragraph styling). The comments explain what is happening.
// Define string attributes let font = UIFont(name: "Georgia", size: 18.0) ?? UIFont.systemFontOfSize(18.0) let textFont = [NSFontAttributeName:font] let fontItal = UIFont(name: "Georgia-Italic", size: 18.0) ?? UIFont.systemFontOfSize(18.0) let italFont = [NSFontAttributeName:fontItal] // Create a string that will be our paragraph let para = NSMutableAttributedString() // Create locally formatted strings let attrString1 = NSAttributedString(string: "Hello Swift! This is a tutorial looking at ", attributes:textFont) let attrString2 = NSAttributedString(string: "attributed", attributes:italFont) let attrString3 = NSAttributedString(string: " strings.", attributes:textFont) /…

Swift: Use for-in loops with your own sequence types

For-in loop The for-in loop might well be familiar to you from working with arrays. For example: let intArray = [1,2,3,4,5,6] for int in intArray { println(int) } Here each value in the array is iterated over and returned as the value (in this case named int) within the loop.
Build your own sequence and generator We can use the for-in loop to iterate over our own types that adopt the SequenceType protocol as is explored in this post.

There are two requirements that the SequenceType protocol makes of a Type that adopts it: (1) the type must contain a method to return an instance of a Type that adopts the GeneratorType protocol, (2) it must typealias the name of the generator type to GeneratorType. And these requirements in their barest form might look like this:
struct MySequence:SequenceType { typealias GeneratorType = MyGenerator func generate() -> GeneratorType { var gen = MyGenerator() return gen } } Next, because we are instantiating a generator (as we …