Archive for July, 2014

Swift: Command line boilerplate

import Foundation

let argv = NSProcessInfo.processInfo().arguments
let appname = (argv[0] as String).bridgeToObjectiveC().lastPathComponent
let argc = argv.count

func usage() {
    println("Usage: \(appname) arguments")
    Foundation.exit(-1)
}

if (argc < 2) {usage()}

Swift: Project Euler Challenge – Fibonacci

Today’s challenge is Euler problem #2. I wanted to start with a less intense problem yesterday because I felt that despite its low Project Euler number, that Problem 2 has a lot more interesting things going for it. Here’s the basic problem:

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

When I first solved this problem as I was just learning Swift, I did so in a fairly obvious way, which is as you see here:

var fib = [Int]()
fib += 1
fib += 2
var sum = 2
while fib[fib.count - 1] < 4000000 {
    fib += fib[fib.count - 2] + fib[fib.count - 1]
    let lastItem = fib[fib.count - 1]
    if lastItem < 4000000 {
        if lastItem % 2 == 0 {
            sum += lastItem
        }
    }
}
sum

But coming back to it later, I was inspired to completely re-think the problem, to try to, how do I put this?, make it Swiftier, put more Swift in it, Swifticize it.

Here’s what I ended up with:

Read On…

Swift: These took far longer to put together than they should have

At some point, I decided I needed to be able to create strings from string formats and arbitrary arguments. In my Objective-C projects, these play a big role in development. I can better do custom logging, create strings for alerts, etc etc. For whatever reason, it took me a really long time to get this functionality implemented.

In the end, here’s the deceptively simple results that took me weeks to get to. They consist of two functions that apply standard Foundation NSString formatting.

func StringWithFormat(format : String, args: CVarArg...) -> String {
    return NSString(format: format, arguments: getVaList(args))
}

extension String {
    func format(args: CVarArg...) -> String {
        return NSString(format: self, arguments: getVaList(args))
    }
}

With these implemented, you can leverage Foundation format strings from your Swift clients. For example, you might use these new items as follows:

"Hello %@ %@".format("Name", "!!") // string function
StringWithFormat("Hello %@ %@", "Guys", "!!") // standalone function
"Hello %d guys".format(23) // works with numbers
var v = UIView()
"View: %@".format(v) // works with objects

Admittedly, these functions are limited in that you can’t print things that you wouldn’t normally print with Foundation, such as CGRect. If you want to extend to printing to special structs and such, you can implement extensions on a class-by-class basis, returning an encodable element in place of an unencodable one.  The following CGRect extension defers to NSValue, which produces a very nice rect representation.

extension CGRect : CVarArg {
    public func encode() -> [Word] {
        var value = NSValue(CGRect:self)
        return value.encode()
    }
}

Once implemented, this functionality is super handy to have around for the structs built into NSValue (CGPoint, CGVector, CGSize, CGRect, CGAffineTransform, UIEdgeInsets, UIOffset on the iOS side). At the same time,  it’s struct specific so not extensible. You have to build an extension for each type.

In Objective-C, I have a great workaround for this — courtesy of Remy Demarest.  It uses ObjC type encoding to produce a value representation for any struct. This doesn’t work with Swift.

#define VALUE(struct) ({ __typeof__(struct) __struct = struct; [NSValue valueWithBytes:&__struct objCType:@encode(__typeof__(__struct))]; })

So I ended up coming up with a completely different approach, namely to capture the print stream debug output. Swift’s print function can pretty much output anything. It can also take a second argument, which is a destination stream. This enables you to grab the print description of any item as a standard String. Rainer B. had a better solution, which follows.

The following implementation creates a prefix. In this example, I settled on %% because it looks very formatty and I thought it wouldn’t be mistaken for anything else or cause confusion in real format strings. So here’s the prefix operator:

operator prefix %% {}
@prefix func %% <T>(item : T) -> String {
    var result : String = ""
    print(item, &result)
    return result
    return "\(item)" // Thanks Rainer B.
}

And you use it like this:

let rectangle = CGRectMake(9, 9, 8, 8)
let resultString = StringWithFormat("Rect: %@", %%rectangle)

I played around with a few other approaches here, such as a standalone “printable()” function, before settling on (for at least the moment) the %% operator. What I really wanted was a way to sort through all the arguments to the StringWithFormat function to determine which ones were not CVarArg convertible and auto-convert them without the %% workaround. If you have any ideas for doing this, please do let me know!

Swift: Project Euler Challenge – Palindromic Numbers

Today’s challenge is Euler problem #4. I like this one in particular because of the fun I had with the string palindrome function. Got a better solution or a tweak? Drop it into the comments, tweet me, or email me.

// Project Euler: Problem 4
// https://projecteuler.net/problem=4

// A palindromic number reads the same both ways. The largest palindrome made from the 
// product of two 2-digit numbers is 9009 = 91 × 99.
// Find the largest palindrome made from the product of two 3-digit numbers.

func isPalindrome(s : String) -> Bool {
    let n = countElements(s)
    if n < 2 {return true}
    if s[s.startIndex] == s[advance(s.endIndex, -1)] {
        return isPalindrome(dropLast(dropFirst(s)))}
    return false
}

func getPalindrome () -> String {
    for d3a in stride(from: 9, through: 1, by: -1) {
        for d3b in stride(from: 9, through: 1, by: -1) {
            for d2a in stride(from: 9, through: 0, by: -1) {
                for d2b in stride(from: 9, through: 0, by: -1) {
                    for d1a in stride(from: 9, through: 1, by: -1) { // Thanks ChristianGeek 
                        for d1b in stride(from: 9, through: 1, by: -1) {
                            let first = d3a * 100 + d2a * 10 + d1a
                            let second = d3b * 100 + d2b * 10 + d1b
                            let product = first * second
                            if  isPalindrome(String(product)) {
                                return String(product)
                            }
                        }
                    }
                }
            }
        }
    }
    return "Not found"
}

getPalindrome()

Swift: nil coalescing

A few nice things this morning

// See: http://twitter.com/iMartinKiss/status/494456905885319169
extension Optional {
    func unwrap(#defaultValue: @auto_closure () -> T) -> T {
        return self ? self! : defaultValue()
    }
}

// See: http://ijoshsmith.com/2014/07/24/nil-coalescing-operator-in-swift/
operator infix !! {}
@infix func !! <T> (value: T?, defaultValue: @auto_closure () -> T) -> T
{
    return value ? value! : defaultValue()
}

And from Phil Holland:

func defaultFallback<T>(a: T?, b: @auto_closure () -> T) -> T { return a ? a! : b() }
func defaultFallback<T: LogicValue>(a: T, b: @auto_closure () -> T) -> T { return a ? a : b() }
func defaultFallback<T: Integer>(a: T, b: @auto_closure () -> T) -> T { return (a != T.allZeros) ? a : b() }
func defaultFallback<T: FloatingPointNumber>(a: T, b: @auto_closure () -> T) -> T { return (!a.isZero && !a.isNaN) ? a : b() }

Swift: Fun with Xcode

This is Xcode.

Screen Shot 2014-07-29 at 2.07.51 PM

This is Xcode on Drugs

Screen Shot 2014-07-29 at 2.07.33 PM

How do I get Xcode on Drugs?

cd /Applications/Xcode6-Beta.app/Contents/MacOS/
./Xcode -NSShowAllViews YES

You’re welcome

Are you out of your mind? Xcode on Drugs? WTF?

It’s not so much the pretty colors as trying to figure out where all the view boundaries are because today I was exploring the playground and trying to figure out some of what makes it tick.

Did you find out?

Meh, a bit. Not everything.

Share

Today I discovered that assistant-window output panes turn blue when you select them. I also discovered that you can sometimes click the bit to the right of the “X” close button and toggle them between full size and partial output.

XcodeScreenSnapz001

What else did you learn?

Finally figured out how to get back the Console output after closing it by accident:

  1. Select the playground (in the Editor pane)
  2. Choose Editor > Execute Playground

Not only does the Console re-appear but you get some great animation effects as the entire playground is reset and run. Mark Dalrymple captured the following awesome “Bill the Cat” effect as the playground ran and output some details to the assistant panes.

billthecat

Did that. The console didn’t come back.

Quit and restart Xcode.

So what does the whole grayed out Reset Playground option do?

Darn if I know. I have never seen that baby un-grayed. If you have any idea, please let me know.

Screen Shot 2014-07-29 at 2.17.29 PM

Swift: Docs generation

Have fun:

#! /bin/sh
# usage: <shellscript> typename
# All credit to @mikeash
echo "import Cocoa\n:print_decl $1" | xcrun swift -integrated-repl | open -f

Some points:

  • Replace xcrun swift with a path as needed (e.g. /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift) if you haven’t selected 6-Beta.
  • No support for UIKit from the command line
  • Case matters

 

That UIAlertView thing: Deprecation and dinosaurs

Are you surprised at how many devs are focused on developing new iOS 7-specific applications this late into the game? iOS 7 has a 2 – 3 month ticking time bomb on it and yet every day, I encounter developers whose primary focus is getting their iOS 7 apps into shape for this autumn rather than building iOS 8 for launch this fall.

Sure iOS 7 and iOS 7 compatibility aren’t going away for a while. Even those devs aware of UIAlertView deprecation are focused on bigger deployment issues. Nearly all of them have irrational partners and bosses who insist on backwards compatibility to roughly the jurassic period. If a new iOS 7 app will work on iOS 8 that’s all they want or need. Taking advantage of iOS 8 features, well that’s for other people.

When you work on books, it’s awfully easy to get stuck in Apple headspace. Take UIAlertView. It’s been deprecated and I keep coming back to that, mostly because deprecated classes aren’t even available in Swift these days. Somehow this keeps resonating to my “It’s dead, Jim! I’m a doctor not a miracle worker” senses. I have to keep reminding myself of the day-to-day realities of the app store as it exists, not as Apple would have it. And yet when developers come to me asking how to build HUDs based on UIAlertView this late in the game, I start going UIAlertController ballistic.

The way I see it, ever since App Store started offering platform-specific upgrades, the pressure to back-support all devices all the time was gone. Unless you’re developing something new but specific to older devices (there’s a big market out there if you’re prepared to fight the tool suite, hi Chris S!), why not keep pushing forward with new releases? It’s not as if older systems can’t still do business with you. And when they upgrade, your newer versions are ready for them to download.

How much back compatibility do you think is necessary, especially if you put out regular updates?  If the world is upgrading with you, what are you gaining from supporting those 10% of users who have access to your product but may not be running the latest version of your software? What am I missing here?

I’m really curious to hear what you have to say.

I’m new to iOS. Should I learn Swift?

In a word? No. If you’re trying to pick up the fundamentals of iOS and its Cocoa Touch APIs, you’re better served at this point by learning Objective C. Swift is a very young language. It changes month by month. Swift might represent the future of iOS development but the present chugs along powered by Objective C.

When you learn Objective C, you buy in not just to iOS but to a wide and healthy ecosystem of books, videos, tutorials, discussion groups, mailing lists and so forth. Yes, you may may argue that those resources skew towards API knowledge over language knowledge — but the language they provide that knowledge in is inarguably Objective C.  You need experience with Foundation, UIKit, Quartz,  AVFoundation, and so forth. Many devs earn that expertise studying examples from GitHub and StackOverflow. In Objective C.

Swift remains immature. You’ll find yourself spending as much time fighting the compiler as learning the language. You create Swift apps line by line, adapting prior platform experience to new language limitations, often struggling with cryptic error messages ($T4 anyone? Unwrapped optional?) that reflect how young these tools are.

Sure, you may bring a lot of general knowledge and a strong computer science background, but what really matters at this point is going into development with an expectation of what you’re trying to build already on the ground. If you already know where you’re going, learning Swift will help get you there. If you’re new to iOS, there’s simply too much happening at once.

Right now many firms are searching for Swift-proficient developers. Whether this is a good idea or not is up for debate but what isn’t up for debate is what they’re really looking for:  people who already know the frameworks and who know how to put software together for iOS. The Swift skills experienced devs are picking up right now are icing on the cake, and an investment in the future.

Thanks, Fyolnish

Swift: Beta 4 very pretty

Many exciting updates in Beta 4. A few thoughts.

Jumpbar support for //MARK:. Finally, Swift has a #pragma mark equivalent

Minimum deployment enforcement. If you’ve been having fun deploying to iOS 6, the party is over.

Strides. Ranges now use stride() instead of by(). I’m still waiting for Xcode to finish downloading so I can test this, but the idea is that you use stride(from, to/through, by) instead. I need to check whether it finally does negative ranges correctly or not.

Access control. This is a biggie and has been long promised by the engineers. You can declare items as public, private, and internal to hide implementation details from client types.

Updated modifiers. Swift is losing several @-keywords, replacing them with unadorned keywords. So instead of @lazy, you have lazy, and instead of @optional you have optional.

CGFloat works right. It should wrap to the proper architectural implementation.

RIP CString. It’s now all ConstUnSafePointer<Int8> all the time. I still can’t get most of my straight C stuff ported but it looks like things are getting closer.

Safer OS X Playboxes. They’re now in sandboxes. Big hat tip to Steven Troughton-Smith on this one.

Shared Playground Data. This looks neat. You access ~/Documents/Shared\ Playground\ Data.