Archive for June, 2014

Building custom extension templates

I recently posted about building file templates to create custom playgrounds. Today, I found myself facing a similar dilemma with application extensions. Working with project templates is a bit fussier than file templates, mostly because of the way you customize and register items.

To start, copy a base template from the built-in templates folder. If working with normal Xcode, this is usually /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates. With Xcode 6, substitute the Xcode6-Beta file name into the path.

If needed, build a path down from ~/Library/Developer/Xcode/Templates/Project Templates/Application Extension and place the copied template there.

Screen Shot 2014-06-30 at 11.58.15 AM

 

I wanted to build an action extension that wasn’t based on storyboards. You’ll notice that there are quite a lot of files in the modern Xcode 6 template. Since I was only interested in Objective C at this time, I ignored everything that wasn’t part of the ActionViewController.[hm] material. I also deleted the MainInterface.storyboard file from the copied extension.

Next, I had to edit the TemplateInfo.plist file so it would create the right kind of Info.plist for me — that is, one that had a primary class to create (NSExtensionPrincipalClass) and won’t try to load a storyboard (NSExtensionMainStoryboard). The problem is that the property list is actually a meta-property list, one that tells Xcode how to create the actual Info.plist from its template. I recommend highly that you copy the default version someplace before you start editing, so it’s easier to recover from mistakes and try again.

For me, the Info.plist section I ended up with after editing looked like this. And yes, this included all the ampersand-escape sequences. (Escaping the escape sequences for this blog post was a lot of fun. not.) That’s because the template file entry for “Info.plist:NSExtension”  includes escaped content in its string values.  So be aware that you’re diving into areas that Apple either never intended to become public or did a really poor job of making publicly editable.

<dict>
    <key>NSExtensionPrincipalClass</key>
    <string>ActionNavigationController</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.ui-services</string>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <string>TRUEPREDICATE</string>
        <key>NSExtensionPointName</key>
        <string>com.apple.ui-services</string>
        <key>NSExtensionPointVersion</key>
        <string>1.0</string>
    </dict>
</dict>

Make sure you include any tweaks needed to make your template sound here, including adding and removing file references needed to build the project. Once you’ve done that, go ahead and create or modify the files you want generated in the template’s folder. For me, I edited ActionViewController.[hm] to produce a skeletal no-storyboard version, centered around a navigation controller so that I didn’t have to resort to a standalone navigation bar with a done button. (If you don’t know what I’m talking about, build a new action extension in some project and see how the built-in skeleton is built. It’s not pretty.)

Finally, you’ll need to update the project template’s identifier (Identifier key at the top of the TemplateInfo.plist file) so it doesn’t conflict with the standard template and add a custom description (Description key) to distinguish its use-case. Quit and restart Xcode, and your new template should be visible and ready to use.

Swift: Watching lazy initializers in action

Applications face intrinsic memory and processing costs. Every object creation and every calculation adds to these costs. Using lazy initializers enables you to optimize performance by delaying expensive operations until they’re absolutely needed.

An object may never get around to using some property during its lifetime. By deferring creation you entirely save that cost. Or, consider a case where initialization is expensive. If you you spread out that cost over time, you have a lower peak demand across the app.

Lazy initializers move operations away from object creation to some point in the future. In Swift, you mark items with the @lazy attribute. This says “don’t perform this initialization until the property is explicitly requested”.

With playgrounds, you can see this attribute in action. In the following example, the lazyProperty does not exist until accessing the description property forces its creation. Once created, the property remains for the object lifetime but it’s also entirely possible for the object to never instantiate that property.

Screen Shot 2014-06-30 at 10.02.46 AM

So you can’t submit your app: Some comforting words

Screen Shot 2014-06-25 at 8.32.49 PM

Yesterday, I was ready to upload a new version of Color App. It’s a big update: one that generates Swift code and supports SpriteKit. When I went to submit it, I got the following error: “Unable to process app at this time due to a general error”.  A general error? Who’s? Mine? Apples? What?

I hopped over to the dev status page and everything reported green. As far as I could tell from that, there were no posted problems at Apple’s end. So I did what anyone else would do. I started googling.  When I did, I discovered that this was not a unique experience, and there was quite a bit of advice out there — nearly all untested, and quite a bit in conflict.

The suggestion that stood out to me the most was “just wait it out, it’s probably iTC’s fault”. However, given the rest of the advice (a lot to do with revoking and re-issuing certificates), I thought the supposed “cure” was bad enough to invest in further searching before taking drastic action.

Turns out that I was not the only one having this problem yesterday and today. Someone started a thread over at devforums. Not only did several people respond to that thread, all of our problems resolved in unison today — and without us having to do anything on our end.

I’m posting this because I hope that the next time this happens someone will come across this post. Hi future frustrated person! Take a deep breath and relax. You did nothing wrong. Pop over to devforums and read the thread. Add your new information. And maybe you can find a group of your own to wait this out with. What you shouldn’t do is panic or start revoking your certificates. If this goes on for more than 24 hours, consider contacting iTunes Connect directly.

Most importantly, you aren’t alone, future person.  I validate your frustration and your fears. But I feel pretty confident telling you that if you just wait it out a bit, everything will turn out okay.

From Brian Musial:

Screen Shot 2014-06-26 at 3.13.49 PM

Swift: Adding custom quick look to your classes

QuickLook is Apple’s embedded quick preview feature. It was first introduced in OS X Leopard back around 2007 or so. Since that time, the concept has broadened. Implementations now appear in iOS and have been added to the latest version of the Xcode IDE.

In Swift playgrounds, QuickLook provides small eye icons in the execution results gutter to the right of the code you enter. When you see an eye, you can tap on it to view a preview of the result that has been generated.

Although Xcode will QuickLook class components, it doesn’t provide direct, custom approach for the class as a whole. Each element is listed, and any inspections of those elements is passed along to embedded inspectors.

What you get generally looks something like this:

Screen Shot 2014-06-26 at 9.55.01 AM

Even when what you really want is more like this:

Screen Shot 2014-06-26 at 9.58.40 AM

 

Fortunately, Xcode and Swift enable you to build your own QuickLook class previews, albeit with limits. To support QL, your class must derive from NSObject. If you don’t explicitly descend from NSObject, throw an @objc annotation in there to provide compatibility, as in the following example.

@objc class BezierCircle {
    var color : UIColor
    var path : UIBezierPath
    var radius : Double
    init (_ radius : Double, _ color : UIColor = UIColor.redColor())
    {
        path = UIBezierPath(ovalInRect: CGRectMake(0, 0, 2*radius, 2*radius))
        self.radius = radius
        self.color = color
    }

By implementing debugQuickLookObject() in your class, you provide the object that Xcode displays in response to eye-icon clicks. For this Bezier circle example, I built an image using the internal path and color:

func debugQuickLookObject() -> AnyObject? {
    UIGraphicsBeginImageContext(CGSizeMake(radius * 2.0, radius * 2.0))
    color.set(); path.fill()
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

As you see in the above image, the gutter text reflects the returned object, in this case a 100×100 image.  If you want to add more information, draw it into the image. You cannot return a tuple with this approach, and your QL return type must conform to the following classes. If you return a custom class other than these, the QuickLook behavior reverts to the default. If your QL object needs to be a tuple of some sort, consider adding a computed property instead.

enum QuickLookObject {
  case Text(String)
  case Int(Int64)
  case UInt(UInt64)
  case Float(Double)
  case Image(Any)
  case Sound(Any)
  case Color(Any)
  case BezierPath(Any)
  case AttributedString(Any)
  case Rectangle(Double, Double, Double, Double)
  case Point(Double, Double)
  case Size(Double, Double)
  case Logical(Bool)
  case Range(UInt64, UInt64)
  case View(Any)
  case Sprite(Any)
  case URL(String)
  case _Raw(UInt8[], String)
}

 

Swift: Type Conversions

Yesterday, I stumbled across this write-up by Mikael Konutgan courtesy of a bit of mistaken attribution. It shows you how to implement custom type conversions, enabling you to bridge Swift classes and functions to structs and non-standard classes. This is helpful information for anyone who has struggled with error messages that state some item “is not convertible” to another type.

What caught my eye was tuples-on-demand. With this, you could use tuple assignment to access struct fields in parallel, as in this example:

var myCGRect = CGRectMake(0, 0, 50, 100)
let (_, _, w, h) = myCGRect

This is not built-in behavior. This derives from implementing the following extension. The __conversion() function enables you to convert from the Core Graphics rectangle structure to a Swift-style 4-tuple.

extension CGRect {
    func __conversion() -> (Double, Double, Double, Double) {
        return (self.origin.x, self.origin.y, self.size.width, self.size.height)
    }
}

Even better, you can overload the conversion and allow type inference to determine the return-tuple style you’re looking for:

extension CGRect {
    func __conversion() -> (Double, Double, Double, Double) {
        return (self.origin.x, self.origin.y, self.size.width, self.size.height)
    }
    func __conversion() -> (Double, Double) {
        return (self.size.width, self.size.height)
    }
}

Although Konutgan’s main point is discussing how you can use this approach to connect Swift classes and structures to Cocoa/Touch equivalents, it’s this flexible conversion that really stood out to me. I should add that the built-in conversion items use the @conversion keyword (thanks SH) but that extra notation does not seem to be strictly necessary in my testing.

There are any number of built-in conversion functions that you can inspect using Command-Click.

Finally? This is not the material you thought you were googling for.

 

Swift: Spiroswiftograph

My kids and I just put together a spirograph playground. The images that follow are mostly based on their choices for major/minor radii and point offsets.

Code:

struct SpirographGenerator : Generator {
    
    var pointOffset, dTheta, dR, minorRadius, majorRadius : Double    
    var theta = 0.0
    typealias Element = CGPoint
    
    init(majorRadius : Double, minorRadius : Double, pointOffset : Double, samples : Double)
    {
        self.pointOffset = pointOffset
        self.dTheta = Double(M_PI) * (2.0) / samples
        self.majorRadius = majorRadius
        self.minorRadius = minorRadius
        self.dR = majorRadius - minorRadius
    }
    
    mutating func next() -> CGPoint? {
        var xT : Double = dR * cos(theta) + pointOffset * cos(dR * theta / minorRadius)
        var yT : Double = dR * sin(theta) + pointOffset * sin (dR * theta / minorRadius)
        theta = theta + dTheta
        return CGPoint(x: xT, y: yT)
    }
}

Screen Shot 2014-06-23 at 6.51.33 PMScreen Shot 2014-06-23 at 6.51.27 PMScreen Shot 2014-06-23 at 6.51.39 PMScreen Shot 2014-06-23 at 6.51.20 PMScreen Shot 2014-06-23 at 6.51.45 PMScreen Shot 2014-06-23 at 6.51.14 PMScreen Shot 2014-06-23 at 6.51.07 PM

Swift: Random Numbers

For your random pleasure. Have fun improving these!

let arc4RandomMax = Double(0x100000000)
func Random01() -> Double
{
    var randDouble = Double(arc4random())
    return randDouble / arc4RandomMax
}

func RandomInteger(max : UInt32) -> Int
{
    return Int(arc4random_uniform(max))
}

Swift: Fetching type encoding

The always wonderful John Holdsworth has put together a replacement ivar_getTypeEncoding() written for Swift classes as part of his XprobePlugin pack. He tells me this is under an MIT license. Update: John asks me to change that to public domain.

/*****************************************************
 ********* ivar_getTypeEncoding() for swift **********
 *****************************************************/

struct _swift_class;

struct _swift_type {
    unsigned long flags;
    const char *typeIdent;
};

struct _swift_field {
    unsigned long flags;
    union {
        struct _swift_type *typeInfo;
        Class objcClass;
    };
    void *unknown;
    struct _swift_field *conditional;
    union {
        struct _swift_class *swiftClass;
        struct _swift_field *subType;
    };
    struct _swift_field *extraType;
};

struct _swift_data {
    unsigned long flags;
    const char *className;
    int fieldcount, flasg2;
    const char *ivarNames;
    struct _swift_field **(*get_field_data)();
};

struct _swift_class {
    union {
        Class meta;
        unsigned long flags;
    };
    Class supr;
    void *buckets, *vtable, *pdata;
    int size, tos, mds, eight;
    struct _swift_data *swiftData;
};

static const char *typeInfoForName( const char *name ) {
    return strdup([[NSString stringWithFormat:@"@\"%s\"", name] UTF8String]);
}

static const char *typeInfoForClass( Class aClass ) {
    return typeInfoForName( class_getName(aClass) );
}

static const char *ivar_getTypeEncodingSwift( Ivar ivar, Class aClass ) {
    struct _swift_class *swiftClass = (__bridge struct _swift_class *)aClass;
    if ( !((unsigned long)swiftClass->pdata & 0x1) )
        return ivar_getTypeEncoding( ivar );

    struct _swift_data *swiftData = swiftClass->swiftData;
    const char *nameptr = swiftData->ivarNames;
    const char *name = ivar_getName(ivar);
    int ivarIndex;

    for ( ivarIndex=0 ; ivarIndexfieldcount ; ivarIndex++ )
        if ( strcmp(name,nameptr) == 0 )
            break;
        else
            nameptr += strlen(nameptr)+1;

    if ( ivarIndex == swiftData->fieldcount )
        return NULL;

    struct _swift_field **swiftFields = swiftData->get_field_data();
    struct _swift_field *field = swiftFields[ivarIndex];
    struct _swift_class *ivarClass = field->swiftClass;

    // this could probably be tidied up if I knew what was going on...
    if ( field->flags == 0x2 && (field->conditional->flags > 0x2 || (ivarClass && ivarClass->flags>0x2) ) )
        return typeInfoForName(field->typeInfo->typeIdent);
    else if ( field->flags == 0xe )
        return typeInfoForClass(field->objcClass);
    else if ( field->conditional && field->conditional->flagsconditional->flags == 0xe )
            return typeInfoForClass(field->conditional->objcClass);
        else
            return field->conditional->typeInfo->typeIdent+1;
    }
    else if ( !ivarClass )
        return field->typeInfo->typeIdent+1;
    else if ( ivarClass->flags == 0x1 )
        return field->subType->typeInfo->typeIdent+1;
    else if ( ivarClass->flags == 0xe )
        return typeInfoForClass(field->subType->objcClass);
    else
        return typeInfoForClass((__bridge Class)ivarClass);
}

iOS 8: traits, assets, ridiculousness

Screen Shot 2014-06-19 at 4.52.53 PM

iOS 8 has all the right intentions and none of the right implementation when it comes to asset management. While I get that people will want art that adapts from “compact” to “regular” sizing, creating catalogs with 20 images at a time (for 5 possible platforms: iPhone, iPhone Retina, iPhone 4″ Retina, iPad, iPad Retina, for compact and regular sizing, for both Retina and non-Retina screens) is frankly ridiculous.

Yes, there are items you’ll want to tweak based on orientation, overall size, and whether the application is compacted into just a portion of the screen (or displaying, perhap,s on a Mac or Apple TV) — but you can do this far better with vectors and in-app sizing and layout requests than generating and dropping dozens of images. Even with bitmap rendering, a sensible developer will likely want at most two copies of the asset — one large, one small, that will work on Retina displays. Just let the OS squeeze or downsample or whatever. What’s more, the JSON that powers the asset system is pretty scary at the moment, inconsistent, and undocumented.

I’m feeling pretty cranky right now as I just spent a large part of today exploring the whole trait collection system and finding that it’s very (unsurprisingly) beta and fussy. While I applaud Apple for separating device- and target-specific characteristics into a system of traits, I don’t really feel it is currently put together in a thoughtful and holistic way. It would be way easier if you could just specify the size differential to the layout system rather than dealing directly with twisty little images all mostly alike.

There’s so much I love about adaptable views, the image system so far isn’t one of them.