Archive for June, 2014

Xcode 6: Loving the IB-Renderable Views

Despite my tendency to do most things in code, this stuff is really amazing. Here’s my quick “how-to”, followed by sample code, followed by a few final thoughts.

  1. Create app (I used single view)
  2. Select the app, in TARGETS, add a new Framework & Library > Cocoa Touch Framework target, e.g. CustomViews
  3. Add the .h/.m files to your project, making sure the framework box is checked and not the app one.
  4. Drag a view into your main storyboard. Color the background so you can see it, and adjust its size.
  5. With the view selected, open the Identity inspector. Change the Custom Class > Class to your class name. For example, TestView as in the following code.
  6. Switch to the attributes inspector and adjust the border color, width, and corner radius. The view should update in real time.
  7. Save. Compile. Run.
#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface TestView : UIView
@property (nonatomic) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable NSInteger borderWidth;
@property (nonatomic) IBInspectable NSInteger cornerRadius;
@end

@implementation TestView
- (instancetype) initWithFrame:(CGRect)frame
{
    if (!(self = [super initWithFrame:frame])) return self;
    _borderColor = [UIColor blackColor];
    _borderWidth = 0;
    _cornerRadius = 0;
    
    return self;
}

- (void) setBorderColor:(UIColor *)borderColor
{
    _borderColor = borderColor;
    self.layer.borderColor = _borderColor.CGColor;
}

- (void) setBorderWidth:(NSInteger)borderWidth
{
    _borderWidth = borderWidth;
    self.layer.borderWidth = _borderWidth;
}

- (void) setCornerRadius:(NSInteger)cornerRadius
{
    _cornerRadius = cornerRadius;
    self.layer.cornerRadius = cornerRadius;
}
@end

Key things to notice:

  • The IB_DESIGNABLE keyword before the subclass interface declaration
  • The IBInspectable keywords for the items that show up in the attributes inspector

Beyond that, be aware that the frame is constantly being redrawn. Although you don’t have to use drawRect:, despite what the docs show, you can add live feedback by updating the text for labels or using string drawing in a custom drawRect: routine. Use the TARGET_INTERFACE_BUILDER target test if you want to comment that stuff out for any other use, though. Auto Layout is available both in code for building up the view and in IB for coordinating this view with other views in storyboards and nibs with this stuff. Views don’t have to be simple like this example. You can add subviews and they’ll show up just fine, both in execution and in IB. Although you can’t interact with any controls (for example, buttons or switches) that you add as subviews in your class definition file,  you can connect them to action targets in IB.

iOS 8: Building custom simulators

Right now in Xcode 6, there are plenty of simulators to choose from but did you know that you could create your own simulators and customize them for specific testing needs?

The simctl command line utility, which you find at /Applications/Xcode6-Beta.app/Contents/Developer/usr/bin/simctl, enables you to create new custom simulators built to your specifications.

You start by creating a device, setting its class and its firmware. You discover the list of installed device types and simulator runtimes by issuing the simctl list command.

== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
iPad 2 (com.apple.CoreSimulator.SimDeviceType.iPad-2)
iPad Retina (com.apple.CoreSimulator.SimDeviceType.iPad-Retina)
iPad Air (com.apple.CoreSimulator.SimDeviceType.iPad-Air)
Resizable iPhone (com.apple.CoreSimulator.SimDeviceType.Resizable-iPhone)
Resizable iPad (com.apple.CoreSimulator.SimDeviceType.Resizable-iPad)
== Runtimes ==
iOS 7.0 (7.0 - Unknown) (com.apple.CoreSimulator.SimRuntime.iOS-7-0) (not installed)
iOS 7.1 (7.1 - 11D167) (com.apple.CoreSimulator.SimRuntime.iOS-7-1)
iOS 8.0 (8.0 - 12A4297e) (com.apple.CoreSimulator.SimRuntime.iOS-8-0)

For example, I might want a 7.1 install on an iPhone 5 to test my Fidget software. You provide simctl with the reverse-domain specifiers for each. So with these constants, the command I issue to create this simulator is as follows:

simctl create Fidget71iPhone5 com.apple.CoreSimulator.SimDeviceType.iPhone-5 com.apple.CoreSimulator.SimRuntime.iOS-7-1

Once built, issue the list command again to retrieve the UUID for your new device. You supply this UUID with each command to control your simulated device.

...
== Devices ==
-- iOS 7.0 --
-- iOS 7.1 --
    iPhone 4s (07357684-4C14-49A1-BD57-8C435CE7611E) (Shutdown)
    Fidget71iPhone5 (D6E1DD7F-712D-4273-A083-F9C9A12AED38) (Shutdown)
    iPhone 5 (F3FE995D-4808-4153-8800-E4EBB94DCB95) (Shutdown)
    ...

Each simulator is stored in ~Library/Developer/CoreSimulator/Devices. Each device folder stores its contents in the data subfolder. This enables you to hop in and inspect files as you run, for example looking at preferences or examining files in the Documents folder.

Once installed, Xcode presents your custom simulator along side the other standards. You select the simulator in Xcode and run apps as normal. Simctl keeps a running list of device states, so as you test, your device is listed as (Booted). Otherwise it is (Shutdown).

You run the simulator by opening it from its default location.

open /Applications/Xcode6-Beta.app/Contents/Developer/Applications/iOS\ Simulator.app

Then,from the command line, you can issue commands. For example, you can have it open a URL:

simctl openurl D6E1DD7F-712D-4273-A083-F9C9A12AED38 https://ericasadun.com

or add a photo to the photo library on the device:

simctl addphoto D6E1DD7F-712D-4273-A083-F9C9A12AED38 ~/Desktop/test.png

or launch an application:

simctl launch D6E1DD7F-712D-4273-A083-F9C9A12AED38 com.sadun.SwiftWorld

The utility comes with a pretty good help system. Just issue simctl without any arguments (or with –help) for more details.

Found some other cool tricks? Please let me know.
Thanks, “A”

Swift: The Lone Range-r

In Swift, you build ranges using .. and … operators. The two dot version denotes a “half closed” range that spans between the first argument up to but not including the second. The “closed” operator uses three dots. In its default format closed ranges go from the first argument up to and including the second. The first of the following examples prints out 1 through 4, the second 1 through 5.

for i in 1..5 {println("\(i)")}
for i in 1...5 {println("\(i)")}

So what happens when you reverse those parameters and try this with 5..1?

for i in 5..1 {println("\(i)")}

What you get is an infinite loop, as i goes from 5 to 6 to 7 and so forth. To get the behavior you expect, use  .by(), a function built into the range structure. This takes one argument, a step differential applied at each iteration.

for i in (5..1).by(-1) {println("\(i)")}

When you run this example, the half closed arguments produce the sequence 5, 4, 3, and 2. So what happens when you use full closed arguments? Not what you expect. The … operator adjusts the final argument to its next value. So when you run

for i in (5...1).by(-1) {println("\(i)")}

you get 5, 4, 3 and not 5, 4, 3, 2, 1. Lily B tells me that that’s because a…b is defined as a..advance(b,1).

One last fun thing. Try using the built-in generate() function to establish a range generator from your range and then call it a few times. You’ll see the generator move through the values in your range at each call, returning nil once it passes the range’s end index.

range = 1..4
var generator = range.generate()
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()

The generate() function returns a RangeGenerator. If you want to try a flipped range out, skip generate(). The by() function returns a StridedRangeGenerator. So you don’t call range.by(-1).generate(), as you’ve already created a generator.

Swift: Structs

More than you can shake a stick at.

Array
ArrayBuffer
AutoreleasingUnsafePointer
Bool
CConstPointer
CConstVoidPointer 
CMutablePointer
CMutableVoidPointer 
COpaquePointer 
CString 
CVaListPointer
CollectionOfOne
ContiguousArray
ContiguousArrayBuffer
Dictionary
Double
EmptyCollection
EmptyGenerator
EnumerateGenerator
FilterCollectionView
FilterCollectionViewIndex
FilterGenerator
FilterSequenceView
Float
Float80
GeneratorOf
GeneratorOfOne
GeneratorSequence
HeapBuffer
ImplicitlyUnwrappedOptional
IndexingGenerator
Int 
Int16 
Int32 
Int64 
Int8 
IntEncoder 
Less
MapCollectionView
MapSequenceGenerator
MapSequenceView
ObjectIdentifier 
OnHeap
PermutationGenerator
Range
RangeGenerator
RawByte
Repeat
ReverseIndex
ReverseRange
ReverseRangeGenerator
ReverseView
SequenceOf
SinkOf
Slice
SliceBuffer
StaticString 
StridedRangeGenerator
String
UInt 
UInt16 
UInt32 
UInt64 
UInt8 
UTF16 
UTF32 
UTF8 
UnicodeScalar 
Unmanaged
UnsafeArray
UnsafePointer
Zip2
ZipGenerator2

Swift: Cocoaphobia

It’s funny how cocoaphobic some people are starting to get. Earlier today, an irc buddy was looking for a string subscripting solution. I offered him this.

extension String {
    subscript (aRange: Range) -> String {
        get {
            var range = max(0, aRange.startIndex)...
                min(countElements(self) - 1, aRange.endIndex)
            return self.bridgeToObjectiveC().substringWithRange(
                NSRange(range))
        }
    }
}

Immediately he recoiled (in text, of course). “I was trying to find an approach that didn’t use the bridge to Obj-C,” he said. After all, he pointed out, what happens when Swift is ported to systems that aren’t Cocoa-based. “I think in terms of long term portability,” he told me. “Swift will be on non-Apple platforms eventually and may or may not bring the baggage of the Apple APIs with them.  I know I’m an old codger when it comes to some of this stuff. I can’t forget the Java problems caused when I was relying on APIs that were sun.* instead of java.*.”

I googled around a bit and found a number of similar solutions that looked more like this:

extension String {
    subscript (aRange: Range) -> String {
        get {
            let start = advance(self.startIndex, aRange.startIndex)
            let end = advance(self.startIndex, aRange.endIndex)
            return self[Range(start: start, end: end)]
        }
    }
}

Lily B explained how this works.  This extension converts from a Range<Int> to a Range<String.Index>, so it calls the pre-existing subscript(Range<String.Index>)->String implementation. Unfortunately, this particular extension produced results that looked like this, which I didn’t think was a massive improvement on Cocoa.

Screen Shot 2014-06-16 at 7.01.51 PM

So, fine. I wrote up this.

extension String {
    subscript (aRange: Range) -> String {
        get {
            // bound the start
            let startValue = min(max(0, aRange.startIndex), countElements(self) - 1)
            var start = advance(self.startIndex, startValue)
            
            // bound the end
            let endValue = min(aRange.endIndex, countElements(self))
            var end = advance(self.startIndex, endValue)

            // return the substring
            return self[Range(start: start, end: end)]
        }
    }
}

After passing that around, I got generally negative feedback. Simon Y told me he’d rather the subscript fail with some loud noticeable complaint  for out of range errors, which he felt was more fitting in a type safe language. As Ken F. adds, “In Cocoa [@”foo” substringWithRange:NSMakeRange(-3,18)] will throw an exception.” So, the code became this, returning an optional type.

extension String {
    subscript (aRange: Range) -> String? {
        get {
            // Check range
            if ((aRange.startIndex < 0) || aRange.endIndex > countElements(self))
            {
                println("Error. Range [\(aRange.startIndex)..\(aRange.endIndex)] is out of bounds in string \"\(self)\".")
                return nil
            }
            
            // Return substring
            var start = advance(self.startIndex, aRange.startIndex)
            var end = advance(self.startIndex, aRange.endIndex)
            return self[Range(start: start, end: end)]
        }
    }
}

But the whole experience really got me thinking. Leaving aside issues of grapheme clusters vs unichars (thank you Ken), why do it all in pure Swift right now other than as an intellectual exercise? Is Foundation suddenly not going to apply in a few months? Should we no longer use UIView? Is there a Swift purity test that I’m missing?

I know this write-up has drifted all over the place but  thought this was both an interesting-enough code story as well as an intriguing set of questions that I’d thought I’d throw them out there for comment. Are you planning to avoid reliance on Foundation where possible or is Swift going to be the new mortar between your Foundation bricks?

Swift: More than you probably want to know about type introspection

Objective-C is very very good at introspection. You can pull things into and out of types, and generally have a blast metaprogramming yourself to whatever goal you have in mind. Swift? Not so much.

Here is the example that the Swift Programming Language manual gives for printing a type name:

class SomeBaseClass {
class func printClassName() {
println("SomeBaseClass")
}

If you type "Hello".dynamicType into a playground, it returns (Metatype), which is as frustrating as it is useless.

This morning, I was kicking around a bunch of code, trying to search for something better. This is where I got started, which is pretty unsatisfying. Everything that follows requires importing Foundation.

func PrintableTypeName(variable : T) -> String
{
    // Test for direct ObjC
    if let v = variable as? NSObject
    {
        return v.classForCoder.description()
    }
    
    // If the object *can* be converted to ObjC type, do so
    // However you lose any specifics as to type
    // Comment this out for more interesting results
    
    if let v : NSObject = bridgeToObjectiveC(variable) as? NSObject
    {
        if let result : NSString = v.classForCoder.description()
        {
            return result
        }
    }
    
    // Native Swift
    switch variable {
    case let test as Double: return "Double"
    case let test as Int: return "Int"
    case let test as Bool: return "Bool"
    case let test as String: return "String"
    default: break
    }
    
    switch variable {
    case let test as Double[]: return "Double[]"
    case let test as Int[]: return "Int[]"
    case let test as Bool[]: return "Bool[]"
    case let test as String[]: return "String[]"
    default: break
    }
    
    return "*Unknown*"
}

Tom D. looked at that, chuckled, and suggested I try doing a protocol instead. So I came up with this, which has the advantage of being shorter and more extendable.

protocol DiscoverableTypeName {
    var typeName : String {get}
}

extension NSObject : DiscoverableTypeName {
    var typeName: String {
    get {return self.classForCoder.description()}}}

So if you want to create a new class, so long as it’s Objective-C-y, it will work automatically — although it returns a “mangled” version of custom class names. (More about that below.) You can also add conformance to structures but you have to do so on a one-by-one-basis.

extension CGRect : DiscoverableTypeName {
    var typeName : String {
    get {return "CGRect"}
    }
}

Lily Ballard finally woke up at that point, having had his morning coffee and a good chuckle at my struggles, and pointed out that I could simply use NSStringFromClass() with an object’s dynamic type. (This doesn’t work for structs.) For example:

class Foo {}
var f = Foo()
NSStringFromClass(f.dynamicType)

This returns _TtC11lldb_expr_03Foo. This is an LLDB “mangled” Swift string that specifies that Foo is a type (_T) of class (tC), folowed by 11-ish bytes of “lldb_expr_0”, followed by 3 bytes of the actual name, Foo. You can demangle that at the command line, although he adds this will probably go away in the GM.

% xcrun swift-demangle _TtC11lldb_expr_03Foo
_TtC11lldb_expr_03Foo ---> lldb_expr_0.Foo

Getting back to my typeName thing, keep in mind that it is bridging to ObjC instead of operating on a Swift string. Once you’ve gotten an ObjC class string, you can get the class back out from that, although I’m not sure how useful that is:

let classTest : AnyClass! = NSClassFromString("Hello".typeName)

As a final note, you can test for class using is.

let testArray : AnyObject[] = ["a", 1, 2.0]
var results : Bool[] = []
for t : AnyObject in testArray
{
results += t is String
}
results

Swift: Fun with Parameter names!

Swift parameters generalize functions. They creates flexible code whose outcome is controlled at run-time by the values they are passed. Here’s a function that builds a UIBezierPath based-wedge. It constructs this from a radius and angle.

Original Function

func BezierWedge(radius : Double, angle : Double) -> UIBezierPath
{
    let path = UIBezierPath()
    path.moveToPoint(CGPointZero)
    path.addLineToPoint(CGPointMake(radius, 0))
    path.addArcWithCenter(CGPointZero, radius: Double(radius), 
        startAngle: 0, endAngle: M_PI * 2 - angle, 
        clockwise: false)
    path.addLineToPoint(CGPointZero)
    return path
}

You call this function with two parameters, both typed as double.

Call #1

BezierWedge(30, 3 * M_PI_4)

Using this approach is practical and simple. As you start to type, Xcode auto-completes the method for you. You replace the placeholders with the two arguments as in Call #1.

The drawback is readability. The great advantage of Objective-C selector in-line argument names lies in the self-documentation it provides. In the original function, you cannot use those labels directly.

Call #2

BezierWedge(radius: 30, angle: 3 * M_PI_4)

If you try to compile the code in Call #2, Xcode complains of “extraneous argument labels”. That’s because internal parameter names can only be used within the function that declares them. If you want to add explicit parameter names you need a different approach.

To enable labels, also called “external parameter names”, add a pound sign before each argument. Here’s an updated function declaration, one that mandates the radius: and angle: labels. Once updated, the compiler accepts call #2 and complains about call #1 (it says “Missing argument labels in call”). If you want, you can alsos

Updated Function Declaration

func BezierWedge(#radius : Double, #angle : Double) -> UIBezierPath {...}

You can mix and match required and positional parameter names if desired. This next declaration requires the angle label but not the radius one.

Mix and Match Declaration

func BezierWedge(radius : Double, #angle : Double) -> UIBezierPath {...}

Call #3

BezierWedge(30, angle: 3 * M_PI_4)

The external parameter name does not have to match the internal one. You can explicitly specify both, as in the following example.

Declaration with distinct external and internal parameter names

func BezierWedge(#radius : Double, acrossAngle angle : Double) -> UIBezierPath {...}

Call #4

BezierWedge(radius: 30, acrossAngle: 3 * M_PI_4)

As you see, the external parameter name is always first, and the internal parameter name second. In this example,”acrossAngle” is the external name. The internal name is “angle”. This variation changes the call (Call #4) but not the internal implementation, which remains as it was in the original function. Using external parameter names helps you add more semantic meaning to the call, differentiating between how the parameter will be used and the name of the parameter’s value.

Swift permits you to assign default values to any function parameter. When added, you can omit a parameter when calling the function. For example, the following function declaration enables you to either or both parameters and make calls #5 – #8. Adding default values implicitly triggers external parameter labels.

Declaring default values:

func BezierWedge(radius : Double = 30, angle : Double = M_PI) -> UIBezierPath {...}

Calls #5, #6, #7, #8

BezierWedge()
BezierWedge(angle:M_PI_4)
BezierWedge(radius:40)
BezierWedge(angle:M_PI_4, radius:40) // Flipped!

To use positional (vs labeled) arguments with default values, use underscores. Underscores are the “don’t care” placeholders of Swift. Here, they say “skip external parameter names”. Calls 9-11 offer examples for the following function declaration.

Using underscores with functions:

func BezierWedge(_ radius: Double = 30, _ angle: Double = M_PI) -> UIBezierPath {...}

Calls #9-#11

BezierWedge()
BezierWedge(50)
BezierWedge(50, M_PI_4)

 Update: Cédric Bozzi pinged me about whether the parameters could be re-ordered. I know they can be in the case with default values but most other experiments raised errors.

Screen Shot 2014-06-16 at 7.44.24 AM

Swift: Labeled Statement Houdinis

In Objective C, commands like break, continue, return, and goto control program flow. The following simple example calls the continue statement each time it encounters a non-zero modulus. This forces the loop to skip to the next iteration so the loop only prints out even numbers between 0 and 12.

for (int i = 0; i <= 12; i++)
{
    if (i % 2) continue;
    printf("%d\n", i);
}

Here is an adjusted Swift version of that loop. I’m not even going to pretend this version makes any sense. (If you run it, your app never terminates. The infinite do while loop continues over and over and over.) Other than the silly do-while loop, the code is more or less similar to the Objective-C example you just saw.

for i in 0...12
{
    if i % 2 != 0 {
        do {
            continue
        } while true
    }
    println(i)
}

One tiny change to this ridiculous code fixes that infinite loop. Swift allows you to add labels to for-in loops. These labels, which may look familiar to D-devs (and, I’m told, Rust), control which flow a continue statement applies to. The next examples adds a label to the for-in loop and the continue statement. Now instead of continuing the do-while loop, the statement continues the for-in loop. You get the even number output you expect.

MyForInLoop: for i in 0...12
{
    if i % 2 != 0 {
        do {
            continue MyForInLoop
        } while true
    }
    println(i)
}

In real life, you’re not going to build an infinite loop just to Houdini your way out of it. However, nested loops and switches will happen. Clarifying the level to which you want to break or  continue provides a clean sense of control over your code, as well as a welcome level of self-documentation.

App Store News

After several years of bother trying to get App Store to work with my first-gen-app update, ToDo finally got updated. It should be live by tomorrow. In the past 2-3 years of trying to get this submitted, I actually rewrote the app completely several times, getting it updated for the iPhone 5 (remember that!?) and more recently for iOS 7. Now that it’s finally (finally!) gotten through, let me know how it works. If you have any feature requests / bug reports, send them to me by email.

In related matters, there’s a brand new version of PasteCatcher also going live.

 

Swift: Calling Swift code from Objective C

The topic came up over on irc about whether you could build Swift classes and call them from Objective-C. I headed over to “Using Swift with Cocoa and Objective-C” and the docs seemed to be clear that this was possible. So I created the following swift app. It’s not much of an app and I’ve got everything pretty much marked out with the @objc keyword.

import Foundation
@objc class TestClass : NSObject
{
    @objc func test() -> NSString
    {
        return "Generated by Swift"
    }
}

After a bunch of googlage, I found this q&a over at Stack Overflow, which helped me get through the remaining steps which were these. (I haven’t really had a lot of time to test them, so if you find any I could skip / tweak, let me know!)

1.  Select your target, and in Build Settings, edit your Packaging > Product Module Name > to your project name

2.  In your Objective-C class, import “<name>-Swift.h”, for example “Test-Swift.h”, matching all the bits before the hyphen to the name from step 1.

Compile and run.

I did not need to use the Objective-C bridging header and I ended up deleting it from my project (making sure to clear it out from my build settings as well.)

I’d like to know exactly how much “@objc”-ing is really necessary and whether the default project name is enough without step 1. That will, however, have to wait because it’s Friday, it’s late, and I just spent many hours getting my SpriteKit visualizer stuff updated for iOS 8, so I only had a little time for this.