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()}
Archive for July, 2014
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:
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 resultreturn "\(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.
This is Xcode on Drugs
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.
What else did you learn?
Finally figured out how to get back the Console output after closing it by accident:
- Select the playground (in the Editor pane)
- 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.
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.
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.