Archive for August, 2014

Swift: Command-line basics

Just because someone wandered along today asking about input from stdin. No guarantees about edge conditions.

import Foundation
import Darwin

var myString : UnsafeMutablePointer<Int8> = UnsafeMutablePointer.alloc(100)
println("Enter your name")
fgets(myString, 100, stdin)
let myName = String.fromCString(myString)
println("Hi \(myName!)")

Auto Layout: iOS 8

It’s been a pretty exciting summer as far as Auto Layout goes. I’m busy going over material so I can get some dates and work estimates to Trina on a possible 3rd edition of Auto Layout. Between Swift, OSX, iOS 8, and whatever is going to be announced in September, it looks like a particularly interesting place to be.

I can’t tell you how thrilled I am about active, the property that self-installs and removes constraints to their natural destination. I submitted my first radar on this back before the first edition was even published. Now with the third edition, I suppose I’ll be all “Yeah, that’s my radar baby!”

The long iOS 8 summer first gave us left and right layout guides, a la the top and bottom guides we first encountered in iOS 7 but they soon disappeared and have since been replaced by a suite of Margin-based layout attributes:

    NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
    NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),

Comments and properties in the UIView header file indicate a layout tree of margins. I think it’s fair to assume this ties into the adaptive application that runs properly both on full-screen as well as side-by-side.

/*
 -layoutMargins returns a set of insets from the edge of the view's bounds that denote a default spacing for laying out content.
 If preservesSuperviewLayoutMargins is YES, margins cascade down the view tree, adjusting for geometry offsets, so that setting the left value of layoutMargins on a superview will affect the left value of layoutMargins for subviews positioned close to the left edge of their superview's bounds
 If your view subclass uses layoutMargins in its layout or drawing, override -layoutMarginsDidChange in order to refresh your view if the margins change.
 */
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0); // default is NO - set to enable pass-through or cascading behavior of margins from this view’s parent to its children
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);

Unfortunately, the material from WWDC is light on details and these updates didn’t take place until fairly recent betas. Got any insights into how this material will play out? I’d love to hear it. (And thanks in advance!)

Swift: Embettering solutions

With Swift, there’s almost always a better way to do things and when you get to that better way, it just rings with “of course”-ness.

As usual, this started as a question from a participant in #swift-dev. “This doesn’t work,” he said, and pasted the following.

func continueGame() {
    if self.gameLogic.count == 0 {
        return
    }
    self.gameLogic[0]()
    self.gameLogic.removeAtIndex(0)
}

So I started kicking the wheels on it. To get going, I decided to use the following array of closures to test my approaches.

[Void -> Void] = [{println("one")}, {println("two")}, {println("three")}]

First, I explained about using a generator and the next() function:

var myarray : [Void -> Void] = [{println("one")}, {println("two")}, {println("three")}]
var mygenerator = myarray.generate()

if let closure = mygenerator.next() {
closure()
}

if let closure = mygenerator.next() {
closure()
}

if let closure = mygenerator.next() {
closure()
}

That wasn’t practical for a generalized implementation.So I built a few loops that eventually ended up like this:

while true {
    if let closure = mygenerator.next() {
        closure()
    } else {
        break
    }
}

But Ken Ferry took one look at that, laughed, and suggested the following (far more elegant) solution instead:

while let closure = mygenerator.next() {closure()}

Beautiful and simple. Thanks, Ken.

Swift: Converting values to enumerations

Yesterday in #swift-lang, an enumeration discussion buzzed. A chat participant asked, “Is there any way to go backwards in an enum? I want to look up an enum based on a value.” The answer is simple and accessible. Creating enumerations from values returned by services and function represents an important touchpoint in Swift development.

RawRepresentable

The RawRepresentable protocol consists of two underlying functions: toRaw() and fromRaw(). These enable you to transform enumerations to and from underlying data states.

protocol RawRepresentable {
    typealias Raw
    class func fromRaw(raw: Raw) -> Self?
    func toRaw() -> Raw
}

For example, if you base your enumeration on integers, you can use the underlying sequence to move to and from that representation.

enum Nums : Int { 
    case Zero
    case One
    case Two
    case Three
}

var z : Nums = Nums.fromRaw(2)!
z == .Two // true
z == .Three // false

This example uses an Int raw-value type for its underlying representation. The type appears just after the name of the enumeration.

Fun with Raw Values

The enumeration values do not have to exactly match 0, 1, 2, etc. For example, you might assign arbitrary values to the enumeration entries.

enum Nums : Int {
    case Zero = 5
    case One = 30
    case Two = 15
    case Three = 20
}

var z : Nums = Nums.fromRaw(20)!
z == .Two // false
z == .Three // true
println(Nums.Three.toRaw()) // prints 20

Nor are your raw-convertible enumerations limited to integers. You have access to any equatable literal, specifically integer literals, floating-point literals, string literals, booleans, and nil. For example, you might use strings as raw values:

enum Lets : String {
    case X = "x"
    case Y = "y"
    case Z = "z"
}

var zz = Lets.fromRaw("z")
zz! == .Z // true
println(Lets.Y.toRaw())

Each case must declare a unique name and value. If you skip the value for integers, as in the first example in this post, they implicitly inherit their order. The count starts at zero and increases monotonically from there.

Raw vs Associated Values

Don’t confuse raw values with associated values. A raw value is constant across all uses of an enumeration. They are defined in the enumeration declaration at compile time. Associated values enable you to store typed information in an enumeration. These are defined at runtime.

enum CocoaResult {
    case success(NSObject) // associated success value
    case failure(NSError) // associated error value
}

Swift: Capturing references in closures

Consider the following code snippet. It creates a closure that prints out the value of the variable i. When it runs, should it print out 25, the value of the variable at the time the closure was created, or 35, the current contents of the memory pointed to by the variable reference?

var i = 25
var cl = {println(i)}
i = 35
cl()

If you paste this snippet into a playground, you’ll find that this code prints 35, and not 25. That’s because Swift closures default to capturing references, not values. To change this behavior and capture the value, use a capture list, as in the following example.

var i = 25
var cl = {[i] in println(i)}
i = 35
cl()

The use of [i] enables you to capture the value of i at the time you create the closure instead of at a later runtime.

Capture lists appear as the first item in a closure. They’re listed before any parameter clauses or identifier lists and require the in keyword to be used. For example, here’s another closure. This one is String -> Bool. It more or less does the same work as the previous closure but offers extra syntactic elements so you can see a capture list in a more complex setting.

var anotherClosure = {
    [i] (x : String) -> Bool in
    println(i)
    return true
}

Here’s another example, one that uses a class instance instead of an integer.

class MyClass {
var value = "InitialValue"
}

var instance = MyClass() // original assignment
var cl2 = {[instance] in println(instance.value)}
instance = MyClass() // updated assignment
instance.value = "UpdatedValue"
cl2()

If you omit the [instance] in capture list, this example prints out “UpdatedValue”, the value associated with the updated variable assignment. With the capture list, it prints “InitialValue”. This is the value stored by the original assignment.

When working with classes, a capture list can add modifiers to captured elements, specifically weak, unowned, unowned(safe) and unowned(unsafe). According to the reference material I’ve been reading, you most commonly see modifier usage when you want to capture self without reference cycles. The Swift Programming Language offers the following example. Here, the capture list enables you to capture the reference to self as an unowned — instead of strong — reference, avoiding reference cycles.

lazy var asHTML: () -> String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)"
        } else {
            return "<\(self.name) />"
        }
    }

Thanks Lily B.

iOS Utilities: UIImage from PDF

I’ve posted before about how the new PDF support in asset catalogs doesn’t really do what we expect (offer resizable vector assets). To make up for that, here’s a class that loads images from PDF files directly, building them to whatever UIImage size you need. Supply a path to the image and a target size, height, or width. If using a size, the functions will scale-aspect-fit to that target. With width or height, they’ll use the built-in aspect and build an appropriately sized partner dimension.

This class is part of my useful things repo, which is where I stash stuff that people may generally find useful. A bunch of classes and utilities are tied to my InformIT write-ups, but others meander there over time because I was inspired for whatever reason.

 

Swift: Calling Swift functions from Objective-C

It’s a lot easier than the docs make it out to be, especially if you’re just using a single target. Here’s my Swift file. Make sure you use the @objc keyword to tag your Swift classes so they’re available to your ObjC ones.

import Foundation

@objc class TestClass {
    class func `new`() -> TestClass {
        return TestClass()
    }
    
    func testFunction() {
        println("This function works")
    }
}

And here’s the Objective-C client:

#import "AppDelegate.h"
#import "TestProject-Swift.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    TestClass *instance = [TestClass new];
    [instance testFunction];
    return YES;
}
@end

The secret here is to import the name of the target in this case “TestProject” with the “-Swift.h” extension. Xcode builds this for you and hides it behind the scenes in the derived data. For the above example, mine was left at: DerivedData/TestProject-aqpeqeuqusyzdtcqddjdixoppyqn/Build/Intermediates/TestProject.build/Debug-iphoneos/TestProject.build/DerivedSources/TestProject-Swift.h

The .h file is actually quite interesting. Here is the interface that was built from my Swift code:

SWIFT_CLASS("_TtC11TestProject9TestClass")
@interface TestClass
+ (TestClass *)new;
- (void)testFunction;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

There’s also a bit of fascinating cookiecutter set-up to be found in the header file. I encourage you to take a peek.

Swift: When Cocoa and Swift collide

Consider the following code. Notice anything…unusual?

init(host: String) {
        self.host = host
        self.protectionSpace = NSURLProtectionSpace(host: self.host, port: 0, `protocol`: 
            "http", realm: nil, authenticationMethod: nil)
    }

Specifically, check out those back ticks used in-line as part of the method signature. They’re required here because the word protocol, in addition to being part of the method name, is a reserved word in Swift. The back ticks enable you to differentiate reserved words and identifiers.

Swift, Xcode: Beta 6 accessing Swift-native definitions

Having any problems in Swift getting access to native definitions through Command-click? You’re not alone. (As one person put it, “b6 is [colloquial expression of extreme disappointment] even by Xcode beta standards”) Here’s a workaround.

Select any Foundation item like NSString and Command-click it like you used to. In the definitions file, use the Jump bar to move from Foundation > NSString > NSString to Swift.

Update: If Command-Click is not working within source code, try quitting/restarting Xcode (thanks Argyrios K.). Still borked for me in Playgrounds.

XcodeScreenSnapz001

 

This brings you to the Swift definitions you were trying to reach. Copy them to a file somewhere for easy reference.

Screen Shot 2014-08-20 at 9.59.45 AM

 

Swift, Xcode: There are many betas. I am number 6. You can call me “Caprica 6”

Not a huge number of changes this week.

Having troubles opening Beta 6? Gus Mueller has an answer. Make sure to adjust the name of the app as needed, especially if you’ve renamed it as I have to keep your Keyboard Maestro macros running:

xattr -d com.apple.quarantine ./Xcode6-Beta.app

Goodbye .hasValue. I loved you  In Xcode 6 beta 6, (I’m sure there’s another 6 in there somewhere to make this the release of the beast) hasValue is gone. This makes me a little sad. Its semantic richness has been removed, a notes says “use != nil instead”. Syntactically fine, but the concept of “this container holds a payload” has gone away.

The positive test for optionalVariable.hasValue {…} will stick around, but a payload-check is now if optionalVariable == nil instead of if !optionalVariable.hasValue, which I found better told the story. The test against nil is handy and I don’t mind it but I don’t think it’s a superior option when evaluated against its brethren.

HomeKit accessory simulator Now you can pretend to turn lights off and on — even if you don’t own a fancy thermostat!

Foundation conformance updates. Remember all those T!’s I was recently complaining about, the ones that made no sense at all in Cocoa APIs? Many of them (officially a “large number”) have been audited for optional compliance.  That means Beta 5 calls like sendAsynchronousRequest(request: NSURLRequest!, queue: NSOperationQueue!, completionHandler handler: ((NSURLResponse!, NSData!, NSError!) -> Void)!) will now better match real world use.

In Beta 6, this call has been updated to sendAsynchronousRequest(request: NSURLRequest, queue: NSOperationQueue?, completionHandler handler: ((NSURLResponse!, NSData!, NSError!) -> Void)?), so the handler closure is still completely borked but at least the primary parameters are more thoughtfully assigned. At some point they really need to either introduce a Results enumeration (with value and error) or fix this to all optionals.

PRO TIP: When filing radars about API migration regarding implicitly unwrapped optionals, include #IUO in the subject line. Apple requests that you do not file radars about APIs that remain wrong, only those that were improperly converted away from IUOs. So I’m completely at a loss about what to do here. Apple writes, “Do not file feature requests about APIs that are still marked as T!, we know about them.” Well, okay then.

Bitwise operators are more NSFriendly. Apple writes “RawOptionSetType now implements to BitwiseOperationsType, so imported NS_OPTIONS now support the bitwise assignment operators |=, &=, and ^=”

Strings append but won’t concatenate. Remember the changes to Arrays back in Beta 5 — the ones where you could append two arrays but not add a new item? It now applies to Strings as well. You cannot add characters to strings — convert them to strings themselves and then add them.

Better voiding through science. C APIs that use void* will preserve the Void typealias.