Friday, August 21, 2015

Just discovered iTunes Connect - Manage iCloud Download Settings

When you have an app for sale and you haven’t logged into iTunes Connect for a while, you don’t often see new features added. The Manage iCloud download settings for this app in the Pricing tab is one such feature that escaped my attention…until now!

Mange iCloud Download Settings

Super handy if you need to control this more tightly.

Friday, July 31, 2015

How To Write a Swift Generic Function Based Only On Return Type

TL;DR Annotate the return variable with a type, e.x. let foo:String? = Utility.nullableValueFromKey(“identifier", dictionary: jsonDictionary)
Versions: OS X 10.10.4  Xcode 6.4 iOS SDK 8.4 

When I started working with Objective-C coming from .NET, one of language features that I missed the most was Generics. They solve a whole class of problems that are tedious and/or require way more code than without generics. When Swift was announced with Generics...

Finally...It's Done

But Generics can be hard, thinking in T for any giving problem can make you a little crazy, especially when the compiler keeps yelling at you.

In Swift 1.0, I used generic functions to help parsing JSON server responses, the functions worked, but they were less than ideal.

The typical problem I wanted to solve was getting a primitive type out of the response dictionary that could be null.

I ended up with this function to do the trick:

class func originalNullableValue<T>(valueType: T, key: String, dictionary: NSDictionary) -> T? {
    var value:T? = nil
    var valueTemp = dictionary[key] as AnyObject! as? T
    if valueTemp != nil {
        value = valueTemp!
    }
    return value
}

Ugly! Why did I end up with this? Either I wasn’t smart enough to figure this out or the 1.0 compiler wasn’t.

Smart, but not Smart Enough

Getting either me or the compiler to figure out what type T was without passing an argument of that type into the method, was, well let’s just say it was the solution I found.

What I wanted was this:

class func nullableValueFromKey<T>(key: String, dictionary: NSDictionary) -> T? {
var value:T? = nil
    var valueTemp = dictionary[key] as AnyObject! as? T
    if valueTemp != nil {
        value = valueTemp!
    }
 
    return value
}

So I dusted off the original method and tried making it what I wanted with Xcode 6.4 & Swift 1.2.

Defining it works fine, but If you attempt to call it:

let foo = JSONUtility.nullableArrayFromKey("fooBar", json: Dictionary<String, AnyObject>())

The compiler returns this error:

Argument for generic parameter 'T' could not be inferred

I have no way to know/test if this is the same error that caused me trouble in Swift 1.0, but this time, either I or the compiler were smart enough to figure it out!

All you have to do is add the type to the variable declaration:

let bar:String? = JSONUtility.nullableValueFromKey("name", dictionary: Dictionary<String, AnyObject>())

Flawless Victory

Thursday, July 30, 2015

No Dan Gillmor, Government Should Do Nothing About Android Security

I nearly burst from laughter after reading this tweet and then article by Dan Gillmor:

What’s so funny? The free market is working in this case exactly as intended. A company in the market, e.x Apple, provides mobile devices that are usually secure and updated. Some consumers have voted with their dollars that isn’t as important to them as other criteria, so they bought an Android phone. There is no surprise here that if you buy an Android device, you highly likely will not get updates of any kind, security or otherwise. 

What criteria stops people from buying an Apple device? Let’s return to Mr. Gillmor:

Apple's iOS devices, of course, are part of a tightly controlled ecosystem, and while Apple is far from perfect on security, it does update iPhones. But we shouldn't be required to turn over our computing and communications to control-freak companies in order to get necessary security updates.

So let me get this straight? Mr. Gillmor doesn’t want Apple devices because Apple is a “control-freak” company, so he invites the control-freak government to use laws &  regulations & force Android implementors to be more control freaks about updates…like Apple. LOL. Sure, the government is always the lightest touch!

If Android users thought updates and security where higher priorities than cheap phones or “open source” software, then they wouldn’t have bought an Android device.

Returning this as not a bug, working as intended!

Epilogue

Google made this mess, they can still fix it. They already offer an Android Bug Bounty. They have a generic Patch Reward Program.

Instead of the heavy hand of laws and regulations, Google should start an Update Rewards program.

Every carrier or vendor that releases Android updates in a timely fashion (say within 1 month) gets a payment from Google.

Security Updates pay more than Feature Updates. To really sweeten the pot, Google can pay per user upgraded, get some vendor/carrier incentive to update as many users as possible.

Vendors/carriers have such thin margins, seems like they don’t have the money to cover testing and deploying Android updates without taking a loss.

Use some of that ad revenue to cover the costs. I mean, advertisers should be clamoring for this. After all, how can they trust the ad profiles Google vends with compromised devices?

Monday, July 13, 2015

How to Completely Eliminate UITableView Content and Separator Indent on UITableVIewCell

TL;DR

overridefunc viewDidLoad() {

    super.viewDidLoad()

         

    self.tableView.separatorInset = UIEdgeInsetsZero

    self.tableView.layoutMargins = UIEdgeInsetsZero

}

 

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    cell.layoutMargins = UIEdgeInsetsZero

}

Versions: OS X 10.10.4 Xcode 6.4 iOS SDK 8.4

Almost every iOS app has at least one and usually more UITableViews and associated UIViewController or UITableViewControllers to manage them.

The view’s ubiquity has to make implementing it very tough and I don’t envy the team that has to account for all the use cases.

Over time, UITableView, UITableViewDelegate, UITableViewDataSource, and UITableViewCell have become very large. Throw in their subclasses, UIScrollView & UIView, and developers have to remember a lot of stuff to get all the behavior they want.

Or in this case, don’t want. UITableView enforces default layout margins and separator margins that are not obvious…once you use AutoLayout.

This is what you see in your storyboard:

UITableView Storyboard

 

This is what you see in the app:

UITableView Insets

Notice the left hand margin? There is no option you can change in the Storyboard to fix it, you just get an indent/margin/inset you didn’t ask for. The storyboard doesn’t show this, so I’m not sure if this is a bug in the Storyboard editor, or in runtime in UITableView.

What’s happened is that I added a few AutoLayout constraints to the left red bar (margins t: -8, l: -8, b: -9).

When I do this, the tableView.layoutMargins appear to be their default value of 8. It looks like without AutoLayout, UITableView resets layoutMargins to UIEdgeInsetsZero, but with AutoLayout, it either wants the default margins or there’s a bug.

You have to add the following code to fix the pre-cell tableView display:

override func viewDidLoad() {

    super.viewDidLoad()

         

    self.tableView.separatorInset = UIEdgeInsetsZero

    self.tableView.layoutMargins = UIEdgeInsetsZero

But that’s not enough to get the cells looking right. Based in part on this StackOverflow post, but with my own testing, you have to implement the delegate callback willDisplayCell like this:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    cell.layoutMargins = UIEdgeInsetsZero

}

Why do we have to set layoutMargins again in willDisplayCell? Apparently the cell’s layoutMargins get reset again right UITableView decides where to draw the separator line, so you have to make them whatever you want. Curiously, willDisplayCell has existed since iOS 2, but I don’t remember needing to use it before iOS 8.

Now we get what we want.

UITableView Insets fixed

Another Workaround That’s Incomplete...

This other StackOverflow post mentions the UIView property preservesSuperviewLayoutMargins. It defaults to NO/false, but for a UITableViewCell is set to YES/true.

You could have mostly solved the problem by explicitly setting that property to NO/false, but it would not have fixed the separator issue.

iOS 9 Beta 

I haven’t run through this on iOS 9 beta, so I don’t know what the the default indent situation is there.

Friday, July 10, 2015

Change the Global Tint in an Xcode Storyboard

TL;DR Look at the File Inspector tab (the one with the blank document) of your storyboard

Whenever I go looking for the Global Tint defined in the main storyboard in Xcode, there’s always a moment of cognitive dissonance.

My problem is that I go looking for some kind of Window object, which of course is how you’d do it programmatically (in Swift):

UIApplication.sharedApplication().delegate?.window!!.tintColor = UIColor.redColor()

The double !! after window is not a typo according to Xcode, though it sure looks weird.

Anyway, I guess nobody wants to make UIWindows things in Storyboards, so this property is stashed under the File Inspector tab!

Friday, June 12, 2015

GitHub is Not Your Resume

Your resume is your resume. 

Your released apps are your resume. 

Your released sites are your resume. 

Your published blog posts are your resume.

Your contributions to widely used open source software, some of which might be hosted on GitHub, are your resume. 

Your public repo that you're the sole contributor to and isn't a shipping product is not your resume

Hiring managers screening applicants don't have time to pull 3+ repos, attempt to compile them, and then read the source to see what a 10x dev/rockstar/ninja/special snowflake you are.
 

Thursday, May 14, 2015

Thursday, May 07, 2015

Cocoapods use_frameworks! Means A Bridging Header Not Required for Objective-C Pods in Swift

TL;DR Use standard "Import Framework" in Swift instead of the Obj-C bridging header for Obj-C Cocoapods with use_frameworks! in your Pods file
Versions: OS X  10.10.3 Xcode 6.3.1 iOS SDK 8.3  Cocoapods 0.36.1

This just wasn't obvious at all. I've been using Swift & Cocoapods < 0.36 since Xcode 6 shipped. While versions < 0.36 did not work with a Swift framework like Alamofire, you could use Objective-C pods and let them get compiled as a static library as long as you used the Objective-C bridging header to import the header(s).

With Cocoapods 0.36 and above, you can have Swift frameworks as Pods. To make that work, you have to put the use_frameworks! keyword in your Pods file. My brain misunderstood Use frameworks instead of static libraries for Pods because it automatically inserted for Swift before the Pods in that sentence. 

Took me a couple hours this morning to work out all my Pods might be framworks. I'm not the first person to figure it out, just a few days ago, Johannes Luderschmidt published a blog post with the solution which put on the right path. All Pods using use_frameworks! are frameworks, not just the Swift pods. A problem like this is where experience with Xcode can really work against you. You start tweaking Header Search Paths,  Framework Search Paths, User Header Search Paths, and the Always Search User Paths (docs: disabling it is strongly recommended) settings in desperation because that's usually where these problems lie. Especially when the first compiler error in your project after putting use_frameworks! in your Pod file is that the header for come Objective-C pod can’t be found.

But that’s totally down the wrong rabbit hole. I’m using the Obj-C MBProgressHUD Pod. What you need to do is:

  1. Remove the #imports from your bridging header
  2. Add Import MBProgressHUD into every Swift file that needs the class.
  3. Fix the enums

You're now using bona fide frameworks, so your enums have moved in flight! You might have a line of Swift that was fine with the bridging header like this:

progressHUD.mode = MBProgressHUDModeIndeterminate

That now has to become this:

progressHUD.mode = MBProgressHUDMode.Indeterminate

Not to big a deal, but the pile of errors might lead you astray that you have a bigger problem than you do if you’re using a lot of Obj-C enums.

Wednesday, April 22, 2015

Deleted my Instapaper Account, Here are Some Stats, and Why the Service Didn't Work For Me

TL;DR 645 Unread 25 Archived 1 Starred

I've had an Instapaper account since 2008 when Marco Arment launched the service until now. I haven’t been using the account for most of the last 2 years, with my last save in June 2014, the only one the whole year.

So I deleted my account. Finally!

The idea never really worked for me, even though I was very excited about it. I’ve always been a news junkie. My routine is daily RSS reader, hourly Twitter timeline, Facebook News Feed mostly on weekends, and daily manual reading of a number of sites. The idea of a service that could generate a newspaper like thing for me to read later seemed great. But I realized that after I went through my usual news reading routine, my attention was exhausted. 

Instead, I used Instapaper as a bookmarking service for “important stuff”, longer form deeper think pieces I thought I absolutely had to know and would get to later. That also turned out to be untrue. Out of the 671 links I added to Instapaper, how many did I actually read? 26! 3.8%. That’s way lower than even I expected.

I’ve been using the Reading List feature built-in to Safari on iOS and OS X, but it’s where links kind of go to die for the same reasons as Instapaper, I just don’t go there, does’t fit into my routine. Bookmarks are a similar story, only the Bookmarks on my favorites bar see any action.

What I think I might need is something to save links grouped by research topic, not just one big list. Bookmark Folders kind of serve that purpose, but it’s not really an elegant or searchable tool.

I’ve also kind of become one of those people on a desktop browser that just leaves a browser window open per topic with tabs for each site until I’m ready to deal with it. Safari does an excellent job of keeping this state at the ready in my Dock on OS X.

 

Wednesday, April 08, 2015

How To Use the Spock Live Long and Prosper Emoji on iOS 8.3 & OS X 10.10.3

Versions: OS X  10.10.3   iOS 8.3
 
Despite the date, this article by Jason Snell at Six Colors about the Spock Live Long and Prosper hand gesture, referred to as Raised Hand with Part Between Middle and Ring Finger, is not an April Fool’s Joke.
 
iOS 8.3 and OS X 10.10.3 can display the emoji, but it isn’t in the standard Emoji keyboard on either OS yet.
 
To be able to use the emoji on OS X, you can create a text replacement macro to use it now:
  1. Copy the emoji from here: Raised Hand with Part Between Middle and Ring Finger (Blogger keeps double-encoding the emoji and makes it unreadable).
  2. Go to System Preferences -> Keyboard -> Text tab.
  3. Click +.
  4. I used LLAP in the Replace column and the emoji in the With column.
  5. That’s it!
Now when you type LLAP on OS X, you’ll get prompted to use the emoji.
 
Now on iOS:
  1. Copy the emoji from here: Raised Hand with Part Between Middle and Ring Finger
  2. Go to Settings -> General -> Keyboard -> Shortcuts.
  3. Tap +.
  4. Paste the emoji into Phrase.
  5. Type LLAP into Shortcut.
  6. Tap Save.
Now when you type LLAP on iOS, you’ll get prompted to use the emoji.
 
Live Long and Prosper!