Archive for February, 2015

Radar Crankiness

If you’re a regular bug reporter, you know the pain new betas bring. A pile of email in your inbox asking you to test out all your previous issues to see whether they’re resolved in the new beta.

It often feels like a scattershot approach. This past week there was one from back in June. It involved a rather large code base in the sample I’d submitted and I had no interest in trying to re-write however many lines of Swift 0.5 code in Swift 1.2 just to test out a simple bug. I just didn’t care about it any more.

The biggest problem with radars is there’s just no incentive other than the hope things will eventually get better. Plus, there’s the whiplash effect where some things they want you to file dupes “Every radar is a vote!” and the ones where they don’t. For example, Chris Lattner has asked developers not to  file duplicate feature requests for Swift.

Sure, if no one files a radar, there’s a good chance that things won’t get fixed. “But that,” a colleague points out, “is often indistinguishable from the state in which you file them.”

Many devs can simply rely on bug-style herd immunity. You can relax on faith that easily-hittable radars are filed by those more eager, less cynical, and less time crunched than yourself. At what point is “another day, another radar dupe” outweighed by the reward of a possible fix?

That Apple hasn’t instituted some kind of reward system continues to mystify me. Why not earn discounts on yearly licenses or bonus karma for use in the WWDC lottery? Even a free frozen turkey would help motivate not just initial bug filings but also those endless “was it fixed in this beta? or this beta? or this beta?” retreads that follow.

I’m feeling a bit burned out on bugs. What do you think?

Free on iTunes: Singles Gone Wild

For many years, Apple had an iTunes “Single of the Week” program. It primarily promoted new albums around the world, with a rare PR effort that would push the same track in multiple countries.

In the US market, there were actually three programs. One for mainstream artists, another for the Spanish-speaking market, and a “Discovery” program for new artists.

A few weeks back, the “Free on iTunes” section seemed to disappear for a while. When it came back, it seems as if the FoiT program had fundamentally changed. Every week, you can now download numerous free tracks. This morning, I believe there were 10 singles available to try.

As always, some of these tracks are pretty good. Many of them are forgettable. Some of them are awful.

It’s interesting though how much closer this new system matches Amazon’s Free Song system. It feels a little less curated than it used to be. Surprisingly, even with expanded content though, the iTunes free music continues to have far less bad material than you might expect.

Over the years, I’ve discovered some reasonable artists and high quality music. Just be prepared to accept the high quantity of chaff that surrounds the wheat.

Review: Fresh Air offers beautiful weather forecasting

Screen Shot 2015-02-24 at 10.04.31 AM

Yesterday it was cold. Today it is cold. Tomorrow it will be cold. Apparently, it’s going to be cold for the foreseeable future and there’s no place near me to drive to where it’s even the slightest bit warm. Thank you, Mr. Gore.

If the cold is getting you down, let me point you to a beautiful new weather app called Fresh Air. For just $0.99, it provides beautiful screen design, great interactive weather forecasts, clever date book integration and more. It’s not going to improve the outlook but it gets you that information in a visually appealing way.

With it, you can scroll hour-by-hour through the upcoming forecast, with overnight and daytime trends presented with colors, graphs, and icons. There’s a lot of information packed into its sparse design. I particularly like how you can view calendar events with temperatures. That Moms get together at the park on Thursday? Maybe that should move to Starbucks instead.

The app includes several built-in discoverable features and it introduces these with minimalist training hints. The occasional “tap here” or “swipe there” reminders expose these features, without requiring an excess of labels that would kill the presentation. While the app is immediately usable, this kind of training philosophy ensures the best user experience over the long term.

If I had one major complaint about the app, it’s that I can’t remember the name. “What’s that new weather app? That thing? The one I just installed? Was it something something weather something?” In fact, no, it’s Fresh Air, and trying to remember that without having to hop into iTunes to figure out “what is the most recent app on my purchases list” is going to take me some time.  It’s the sort of app you have to remember by putting it in a particular place on your screen but it’s also the kind of quick-reference that you’d want to promote anyway.

Fresh Air is narrow in its scope. It does one job, it does it well, and it’s extremely well priced.

Swift: And Xcode 6.3 beta 2 did drop as the gentle rain

Some highlights.

FUNNER PLAYGROUNDS

Rich documentation markup (reStructuredText) is now supported. The Xcode release notes note that  markups may not always render properly (known 6.3 beta 2 issues). In the following screenshots, the marked up comment (created with a /// indicator) renders properly in 6.3

in 6.1:

Screen Shot 2015-02-23 at 1.28.59 PM

in 6.3:

Screen Shot 2015-02-23 at 1.29.10 PM

Results are now shown in-line instead of the timeline view. So you pop-up a visualization by clicking the eye in the results gutter or…

Screen Shot 2015-02-23 at 1.33.57 PM

or by clicking the value history dot:

Screen Shot 2015-02-23 at 1.35.37 PM

The three buttons at the top right indicate graph mode, current value, and “all values”, a history list of values.

What’s great about the inline stuff is that you can more or less close off your assistant editor. I’m still not sure why there’s no timer slider on this new version. Is it gone for good? Oh there it is! At the bottom of the playground pane!

Screen Shot 2015-02-23 at 1.47.06 PM

IF LET REFORM

Beta 2 also introduces extended if let with leading boolean conditionals. You can now perform tests with a boolean phrase before adding a if-let conditional unwrapping:

Screen Shot 2015-02-23 at 1.50.06 PM

 

ZIP LINES!

The new zip function takes two sequences to create tuples.

Screen Shot 2015-02-23 at 1.53.46 PM

OTHER THINGS

  • RIP utf16Count, recently discussed. Instead “use count on the UTF16 view of the String”, e.g. count(string.utf16)
  • More intermittent SourceKitServices crashes have been addressed and “Several common issues affecting the “Convert to Latest Swift” tool have been fixed.”

 

Unreadable PDF. Who knew? (An ode to @ecammtweets)

Screen Shot 2015-02-23 at 11.57.34 AM

My son’s school recently emailed me some forms. I was about to acknowledge their receipt when I discovered I could not read them. Instead of seeing the forms they’d sent, I could only view some message about my PDF viewer (Mail and Finder in this case) not being able to display the file.

“If this message is not eventually replaced by the proper contents of the document, your PDF viewer may not be able to display this kind of document.” It then instructed me to upgrade to the latest version of Adobe Reader, a suggestion that in context seemed slightly hilarious as I wasn’t using Adobe Reader in any fashion at the time.

It turns out that some Adobe PDFs have this marvelous property: They can only be read by Adobe software. It took a bit of googlage until I finally found a site that explained the situation. No Adobe, no read.

Fortunately, I have a version of Adobe CS 4 still installed on my Mac, although it’s held together these days by spit and bandaids. Hello 2008. I was able to get Acrobat Pro running and sure enough, I could open the doc in the app and it was readable.

Naturally, I tried to use OS X’s built-in PDF rendering to print to file. Bzzzzzt. That (of course) was not allowed.

Screen Shot 2015-02-23 at 12.03.17 PM

Thank goodness for Ecamm. Instead of printing to “file”, I used my copy of their Printopia extension ($19.99) to print to my Mac instead. Instantly my unreadable PDF file transformed to a readable one. I simply pulled the rendered PDF out of my Documents/Printopia folder and it was ready to use. Printopia saved the day. Thanks, Ecamm. And hopefully this write-up will be googlable for anyone who encounters the same kind of problem with a PDF file that cannot be read in OS X mail.

As a final note, I’m told that you might be able to contact the person who prepared the PDF and ask them to switch the limitation off and resave. This would allow the document to be opened in any PDF viewer. When dealing with low-level administrative staff employed in the public school system, however, you might just want to know about alternative approaches so you can go-it on your own.

Tokens developer introduces Top Hat for App Store sales reports

Screen Shot 2015-02-20 at 3.02.07 PM

I am a  Tokens fan. Developed by Oisin Prendiville and Padraig Kennedy, Tokens enables you to distribute and track app codes with a beautiful click-to-redeem experience. It’s professional and clean for both you and the reviewers you send the codes to.

Now Supertop, the makers of Tokens, have launched Top Hat. This “sibling” app offers quick access to sales figures via your Mac menu bar. Click on the little hat and view your top downloads and revenues for the day. Top Hat provides instant gratification, with both its immediate overview (as in the screenshot at the top of this write-up) and live links to your iTunes account.

My only complaint is its iOS-only support. My #3 seller is actually a Mac app: the folderol utility that customizes folder icons. With my recent press push (if you want to review it for your blog, please ping me by email!), I am monitoring sales a little more intently than usual. I could not find an option anywhere to enable Mac app stats in the top downloads/revenues list, which lowers the usefulness as I do develop for and monitor both platforms.

The app costs $9, which you commit to after a free 7-day trial. For the price of a couple of beers you get a well designed app by a company that’s built its reputation on solid, well-maintained titles. (And hopefully, one that will soon support OS X reporting as well as iOS. Hint hint hint.)

Top Hat, $9.

Update: The developers sent me a beta that includes Mac support. I’ve run it and can confirm the OS X / iOS joint reporting functionality. They promise they will push this release out quickly.

Swift: Counting Strings (Part 2)

A while back, I posted about counting strings in Swift.  I discovered that countElements() offered the most consistently correct results regardless of string content. Time has passed. With Swift 1.2,  countElements() has been replaced with count(), which of course has made updating code and libraries a great deal of fun because there’s nothing more exciting than a language past its 1.0 debut that continues to change syntax details.

Screen Shot 2015-02-19 at 9.10.37 AM

Last night, I ran into an interesting string counting situation with countElements()/count()/countChocula()  even as I doggedly insisted on its superior correctness in string testing.

Ken Ferry pointed out that the count call requires O(N) time. In comparison, utf16count is O(1). As my previous experiments showed, when you’re using complex strings with emoji, the answer with utf16count will be wrong but as Ken correctly noted, you’ll get the wrong answer really fast. For a 33554432-character string I threw together, that answer took 8.42 seconds with count and 3.6e-05 with utf16count. Pretty big performance difference.

So why do O(1) results matter? As Ken pointed out, “Wrong depends on why you’re looking at it.” There’s no instance in which the utf16count will be wrong for zero length checks, such as if myString.utf16Count == 0. So if you’re going to perform a lot of those tests, it starts to matter. For a zero length string of “”, 100000 comparisons on my Mac mini took 0.015 seconds with utf16Count versus 0.04 for count(), a significant slowdown.

Turns out, however, that there’s an even better solution, which is to check whether the string is equal to “”. Nicolás Alvarez suggested this approach and I put it to the test, again running each comparison 100000 times. Results? Just 0.005 seconds to perform the == “” tests compared to 0.015 for the utf16Count ones.

Update: Davide De Franceschi asks, what about using .isEmpty. Answer: Not too shabby:

0.00494605302810669 // == ""
0.0156670212745667 // utf16count
0.0351709723472595 // count()
0.00633901357650757 // isEmpty

Update Alex Pretzlav adds, Your string counting question reminded me I had written this little guy:

func isEmptyOrNil<C : CollectionType>(x: C?) -> Bool { return x.map { isEmpty($0) } ?? true }

 

Swift: Linearizing code

I like linear flows. With Cocoa calls, I request, check for failure, handle errors, and move on. The step-by-step results are easy to follow, to modify, and to understand many months later.

Quick note: 1.2 doesn’t seem to like the NSErrorPointer pattern I use in this post. You can easily replace with inout error : NSError?

NSString *StringFromURL(NSURL *url, NSError **error)
{
    // Request data
    NSData *data = [NSData dataWithContentsOfURL:url options:0 error:error];
    if (!data) return nil;
    
    // Convert the data to a UTF-8 string
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if (!string) {
        if (error)
            *error = BuildError(1, @"Unable to build string from data");
        return nil;
    }
    
    // Return the string
    return string;
}

The standard Swift equivalent for these checks uses if-let constructs. If-let provisionally assigns a variable to the Some enumeration case. When the optional can be unwrapped, it’s assigned to a local non-optional variable (here, data and string) and used. The if-let else clause handles errors. Unfortunately, the success case tends to be buried in a pyramid of code extending above and below it. Here, the return string success appears smack in the middle of this function.

func StringFromURL(url : NSURL, error errorPointer : NSErrorPointer) -> (NSString?) {
    var error : NSError?
    
    if let data = NSData(contentsOfURL:url, options: NSDataReadingOptions(rawValue:0), error: &error) {
        if let string = NSString(data: data, encoding: NSUTF8StringEncoding) {
            return string
        }
        if errorPointer != nil {
            errorPointer.memory = BuildError(1, "Unable to build string from data")
        }
        return nil
    }
    if errorPointer != nil {
        errorPointer.memory = error
    }
    return nil
}

The following adaptation avoids the if-let pyramid, testing for nil cases instead of Some. It is wordier. It uses more variable declarations. But I rather like the clarity and readability and that the success case appears at the very bottom. I’d imagine this would be far easier to tweak and maintain especially if there are additional steps added at any future time.

func StringFromURL(url : NSURL, error errorPointer : NSErrorPointer) -> (NSString?) {
    var error : NSError?
    
    // Fetch data. Blocking.
    let data_ = NSData(contentsOfURL:url, options: NSDataReadingOptions(rawValue:0), error: &error)
    if (data_ == nil) {
        if errorPointer != nil {
            errorPointer.memory = error
        }
        return nil
    }
    let data = data_!
    
    // Convert to string.
    let string_ = NSString(data: data, encoding: NSUTF8StringEncoding)
    if (string_ == nil) {
        if errorPointer != nil {
            errorPointer.memory = BuildError(1, "Unable to build string from data")
        }
        return nil
    }
    let string = string_!
    
    return string
}

What do you think? Heresy? Approval? Drop a comment.

Folderol FAQ #5: What are these new app options?

Screen Shot 2015-02-16 at 7.41.32 AM

 

Folderol continues to evolve over time. The latest version (1.95) includes some new and re-stated options. A summary:

folders only: This option prevents folderol from coloring non-folder items like text files. It is enabled by default because OS X builds previews for many document types. When colored by folderol, you lose those document content hints.

tint and tag (OS X 10.9 and later)This option enables you to add custom tags as well when coloring items

replace icon entirely with custom image: This option swaps in your source image preventing icons from cropping to folders and other file shapes.

don’t blend custom image with original icon color: some users really didn’t like the way folderol blended images to the default blue folder color. This option better preserves source image hues.

fit custom image to icon: folderol normally adapts any art to the destination geometry, stretching or squashing the art to fit. Enabling this option forces the image to keep its original aspect ratio. This option may add padding effects (letterboxing or pillarboxing) to the final icon.

 

Folderol FAQ #4: I don’t see icons in list view / column view / etc

User writes:

I was very excited when I found out about your app. I rely on the label color function provided by finder,  but find it very limiting as it only has five colors.  But only folders in the icon view show up as colored  using folderol– at least in Mountain Lion.  I like to organize using the column view and the standard Mac color labeling works with that.
If you cannot see the custom folderol icons in any of the Finder views, make sure you’ve enabled icons in the Finder’s View > Show View Options (Command-J) pane. For this user, re-checking “show icons” fixed the problem.
Screen Shot 2015-02-16 at 7.36.53 AM