now

Timothy A. Mitra

artist, podcaster, iOS Developer, Development Manager, technical consultant, lecturer, web developer, and technical writer.

I spoke at the first SwiftTO conference on August 13, 2019. Here’s a link to my talk. 5 Ways to Level Up Your Mobile Development. I gave a preview of the talk at TACOW on July 9, 2019.

In 2016, I was pleased to join TD Bank as a Senior iOS Developer  and subject matter expert, working on their mobile banking platform. I was promoted in 2017 to manager. I am currently a IT Development Manager (iOS) at TD. I got my first TD account in 1979 and I have been a TD Canada Trust client since the early 90’s. So it’s really cool to be working on the apps in at the TD Centre, which was created by one of my favorite architects, Mies Van Der Rohe.

I also host and produce the More Than Just Code podcast, which focuses on iOS development. It is a round table format including developers across North America. My current co-hosts are Jaime Lopez Jr, Mark Rubin,  sometimes Greg Heo and Tammy Coron. I also guest host on the RoundaboutFM podcast.  Aaron Vegh left the show in 2016.

Jaime Lopez Jr, Jonathan Kuehlien and I have been hosting a pop culture sci-fi podcast, Spockcast, centered around Star Trek: Picard and Star Trek: Discovery.

I am still working on iOS apps. This involves updating apps that I have produced for 2 For Life Media, Son House Productions and my own company, iT Guy Technologies. These are some pretty diverse apps in life style, entertainment, productivity and of course games. Apps you can check out are 2life, 2life Baby2life Ultimate Wedding Plannerthe Strombo ShowDevice Tracker and Geese Squad to name a few.

Under the hood, for those who are interested, I work primarily in Xcode with Swift, SwiftUI and Objective-C. I spend a lot of time with UIKit, CoreData, NSURLSession, AVToolKit as well as Sprite Kit and the requisite frameworks needed to manage content in apps. I can also be found wielding design tools to create artwork  and wire frames. Soup to nuts I wrangle all parts to iOS and OS X app development. I also do a fair amount of web development, mostly custom WordPress and app APIs that support the mobile apps.

For more than five years, I have been a member of the RayWenderlich.com tutorial team. I have written a couple of tutorials but lately I have been part of the Articles Team. I recently was involved as Developmental Editor on The Swift Apprentice book which was published in October 2015. I am working on another new project headed up my Ray Wenderlich himself. Stay tuned.

2019 marked my 30th year of using Apple Macintosh computers. It was true turning point for me using Macs and computers in general. I started as one of a few people who worked full-time on a computer and now 30 years later we carry them in our pockets and wear them on our wrists. Access to information is taken for granted.

I am no longer able to teach iOS development outside of TD. My latest course is Swift 101, for persons interested in learning Swift for iOS and OS X. Ongoing courses are on iOS development introduction and advanced. I have also trained users on Objective-C, WordPress, and various Adobe titles for print & web.

During the week of Dec 14, 2015, I taught “Advanced iOS Development” online. We covered some advanced topics on iOS development and Swift.

I continue to provide consulting services in iOS development & IT and I am available for contract work.

A case for the Subscription App Price Model

App development, like art, is an expense of creative energy and effort. Once published, maintenance and upkeep takes a considerable amount of time and skill. Keeping up with changes in technology that Apple and Android add complicate a developers life. Imagine having to update a painting or redo a sculpture in a new medium because the galleries change how your work is to be consumed.

In 2014, the kids decided to drive app prices down to the free model to generate downloads – commoditizing the app business and frankly taking the fun out of this creative outlet.

As a result, People just won’t pay what an app is truly worth. They expect apps to be free. Adding ads to apps is a futile effort as it requires tens of thousands of downloads and repeated use to make even a meager income. Pizza money is what most developers get.

Lately, developers and publishers have landed on the subscription model. If you’re app is compelling enough you can derive a better sustainable, recurring income over time. However, It takes a long time to reach an equilibrium.

You also have to factor in the market you are creating an app for. If the market is small, Eg. the Go life or death scenario app, then you need to charge more per month. The app you mentioned wants $13 per month and that may in fact be steep. How many people do you suppose would even download that app in the first place (Boomer)?

Photoshop on iPad can be had for around $20 per month minimum. Adobe is making a killing on their subscriptions. It used to cost $1,500 to upgrade annually. Subscription for the full adobe packed is around $49 – $50 per month – comes out to the same over a couple of years. Adobe also has a lot of mouths to feed. It’s a necessary evil and you’re hooked in. Imagine if your oil paints, canvases and brushes locked at the end of the month if you stopped paying?

Even successful app developers have gone out of business with the subscription model. It’s not a simple hobby and the work: code and design has value.

Bottom line: if you like an app and want to to be improved and maintained then pay your developers. Like any creative pursuit, funds are needed for the long haul.

Maybe $13/mo is too much. The developer may lower the price when no one subscribes. If they’re a smart marketer, they will try other ways to make an income. He’s bringing an incredible domain knowledge to the world of wannabe Go players.

Subscriptions are the model for the foreseeable future. Don’t be to hasty to deny the dev a living.

There ain’t no such thing as a free lunch. Pay your developers.

Error Previewing a Child Theme

This one took me a minute to figure out. I had worked on a child theme in WordPress, but ran into the following error when I tried to use Live Preview:

Twenty Seventeen requires at least WordPress version 4.7. You are running version 4.5.20. Please upgrade and try again.

The strange thing is the version of WordPress version 5.x not 4.5.20. Obviously there was a version conflict somewhere. Googling around produced no hits, that made sense.

The cause was that the version of WordPress on the production site was behind the version on the development site. Who knew? So, I updated the production site to the latest version and the problem went away.

I’m posting this so that it can help others.

Refactoring: Face ID/Touch ID for iOS 13

Back in February 2015, my article on Touch ID was published on raywenderlich.com. It was written in Swift for Xcode 8. Every year or so, I would update the article while I was an author on the iOS Team. Here’s a link to the latest version — How To Secure iOS User Data: The Keychain and Biometrics – Face ID or Touch ID. A few months ago, I had to update one of my own apps for iOS 13 with Apple’s biometric identification framework, Local Authentication. Incidentally, my app was also still supporting Objective-C. Here’s follow up on what I had to change. As a bonus you can also take your user to Settings in case they have disabled

First thing is to add Local Authentication at the top of the Login view controller.


#import <LocalAuthentication/LocalAuthentication.h>

Next create an action for the Touch ID method:

- (IBAction)touchIDAction:(id)sender {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;

NSString *myLocalizedReasonString = @"Used for quick and secure access to the test app";
//...
}

After that we need to check if the device can support biometrics with canEvaluatePolicy and have an error ready.

Inside the touchIDAction add:

if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
error:&authError]) {
// 1. successful steps
} else {
// 2. Oops. There's a error!
}

Inside the canEvaluatePolicy, we’ll use evaluatePolicy:localizedReason:reply. The reply will have a block that either succeeds or fails with our error.

// 1. successful steps.
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates

// using a Keychain utility method to get the email and password
NSString *passwordFound = [KeychainUtils getPasswordForUsername:self->emailTextField.text andServiceName:@"My_app" error:nil];
self->passwordTextField.text = passwordFound;
self->usingSecureID = true; // a Bool I added to keep track
[self loginAction:nil];
[NSLog showWithStatus:@"Logging_In"];
});
});
} else {
// User did not authenticate successfully, look at error and take appropriate action

//I'm using a showAlert method to bring up a UIAlertViewController
[self showAlert: @"There was a problem verifying your identity." withTitle:@"Error!"];
return;
}
}];

What do we do if there is an error enabling Face ID/Touch ID? It could be because the user has disabled the feature. What’s new is that we can now take the user to your application settings — without a hack.

Initially you can pop up an alert to inform the user. Added to UIKit in iOS 8, UIApplicationOpenSettingsURLString lets you add a button to the alert that will take the user to your app in Settings, where they can enable Face ID/Touch ID.

// Could not evaluate policy; look at authError and present an appropriate message to user
NSString *title = @"Error!";
  NSString *message = @"Your device cannot authenticate using TouchID.";
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
// do we need to return animation?
                                                          }];
    // open your app in Settings
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    UIApplication *application = [UIApplication sharedApplication];
    NSString *settingTitle = @"Settings";
    UIAlertAction* settingsAction = [UIAlertAction actionWithTitle:settingTitle style:UIAlertActionStyleDefault
                                                           handler:^(UIAlertAction * action) {
                                                             [application openURL:url  options:@{}
completionHandler:nil];
                                                           }];
    [alert addAction:settingsAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
    return;
}

The whole method would look like this:

- (IBAction)touchIDAction:(id)sender {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;

NSString *myLocalizedReasonString = @"Used for quick and secure access to the test app";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
// 1. successful steps

[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates

// using a Keychain utility method to get the email and password
NSString *passwordFound = [KeychainUtils getPasswordForUsername:self->emailTextField.text andServiceName:@"My_app" error:nil];
self->passwordTextField.text = passwordFound;
self->usingSecureID = true; // a Bool I added to keep track
[self loginAction:nil];
[NSLog showWithStatus:@"Logging_In"];
});
});
} else {
// User did not authenticate successfully, look at error and take appropriate action

//I'm using a showAlert method to bring up a UIAlertViewController
[self showAlert: @"There was a problem verifying your identity." withTitle:@"Error!"];
return;
}
}];
} else {
// 2. Oops. There's a error!

// Could not evaluate policy; look at authError and present an appropriate message to user
NSString *title = @"Error!";
  NSString *message = @"Your device cannot authenticate using TouchID.";
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
// do we need to return animation?
                                                          }];
    // open your app in Settings
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    UIApplication *application = [UIApplication sharedApplication];
    NSString *settingTitle = @"Settings";
    UIAlertAction* settingsAction = [UIAlertAction actionWithTitle:settingTitle style:UIAlertActionStyleDefault
                                                           handler:^(UIAlertAction * action) {
                                                             [application openURL:url  options:@{}
completionHandler:nil];
                                                           }];
    [alert addAction:settingsAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
    return;
}
}
}

Talk: 5 Ways to Level Up Your Mobile Development

Talk Abstract

Making successful apps is daunting. New skills must be attained. Choosing frameworks, and building safe code requires knowledge. This talk covers ways to acquire new knowledge, safe practices, and how to get the various parts of a project done. The work, as it turns out, is more than just code.

Talk Description

Being a successful developer can mean many things. You may want your apps to be used by many people—often, and with pleasure, surprise, and delight. You may also be looking to level-up your career or to teach others. Heck, you might even want to podcast about development. So, how do you get into the position to be successful?

This talk takes a look at techniques to level-up your mobile toolchain. I like to say it takes more than just code to make an app. In some ways, you need to be a multipotentialite. We’ll look at how you can use aspects of several sciences and best practices to tool-up for success. We’ll cover the reasons that make products successful, how to create a community, why it’s important to give back, and how to decide what to include (and what to cut). On the coding side, we’ll look at strategies for good code, technical debt, and project management. We’ll even look at brain science to find out how to retain all of this info and the skills you’ll need to be a success.

Notes

I am a mobile app developer, podcaster and artist. I have taught iOS dev, Swift and Objective-C. I’m currently a Development Manager – iOS at TD Bank. I also run iT Guy Technologies, a software development company in Toronto, Canada. I studied Fine Arts before there were Macs and I’ve worked for many years in software development, IT, graphic design, publishing and printing. I’m the founder, producer and host of the More Than Just Code Podcast — a podcast covering mobile app development & business and SpockCast a sci-fi pop culture podcast. Tim is also co-host of Roundabout Creative Chaos podcast.

I have given several talks over the years. I’ve spoken at 360iDev, Indie Devstock and Expo Canada. I spoken on iOS app development, developer skills as well as macOS and Unix basics.

Points:

  • a short discussion of the More Than Just Code podcast. To give guidance to fellow developers on iOS dev and App business
  • Start with “Why”. Intention is important in what we do and deliver to others.
  • How am I making a difference in other’s lives?
  • How to make a dent in the universe, through your work. Why do we do the things we do and will we be remembered for it.
  • I wrote an article about “Learning After 50”, which lead to brain science and neuroplasticty
  • “Hacking your brain”. How the brain works – a discussion on forming memories and behaviours from brain research and how you can use practice to enhance your studies
  • examples of how I use this new knowledge to learn new songs and instruments. I also use this to learn new skills related to mobile development such as SwiftUI and Combine.
  • Community
  • giving constructive and helpful code reviews and peer reviews.
  • giving back to others in our iOS and mobile dev community.
  • becoming a mentor to others.
  • We are taught how to drive but there is no similar course on how to communicate.
  • looking at the amygdala and neocortex and how they influence our reactions and communication.
  • we all have a negativity bias that leads to self doubt and imposter syndrome
  • the role of Craftsmanship in our work.
  • adopting SwiftUI and Combine and techniques to get involved based on what we learned.
  • where we are in the universe as an object lesson about self importance.
  • concludes with an example of iPad empowering communication.

Command CompileAssetCatalog failed with a nonzero exit code

pulling out hair

Oh my good gravy!

I was working on a cleanly installed Mac after migrating user accounts onto it. My account is not the primary admin account (eg. UID 501). For some reason Xcode was installed with all the permissions set to that primary user, who has yet to log onto this Mac!

I have been having multiple issues trying to get Xcode to build on this Mac — my traveling Mac. I like to leave my bread and butter Mac at home and travel with an 11 inch MacBook Air. Primarily because any other Mac cannot be opened on an airplane, in Economy. I cannot afford to fly business class since the Indie-Apocalypse hit in 2014.

So the owner permissions were all f’ed up, where Xcode does it’s build business. The last straw was the “Command CompileAssetCatalog” failure.

The fix is to change the permissions on the Xcode folder in my own home Library (which all files should be all owed my username.) Pro Tip: replace your username where you see mine — tmitra

cd /Users/tmitra/Library/Developer/Xcode/UserData
ls -la

Checking the ownership of this folder showed I was not the owner. So I stepped back and fixed the permissions on the Xcode directory here:

sudo chown -R tmitra ~/Library/Developer/Xcode

Build and Run.

FWIW I also had to fix permissions elsewhere:

Error: Failed to create temporary directory: /Library/Developer/Xcode/UserData/IB Support/Simulator Devices/

sudo chown -R tmitra ~/Library/Developer/CoreSimulator/Devices

“tmp” couldn’t be removed because you don’t have permission to access it

sudo chown tmitra /Users/tmitra/Library/Developer/Xcode/DerivedData

Your mileage may vary.

Beavers & Bellwethers

This week we follow up on the case of an Oregon man who uses the title “engineer”. Apple lowered its Q1 guidance based on lower expectations. Apple also starts assembling premium iPhones in India. Apple’s new plans may reveal what projects will be worked on around the United States. Netflix has pulled iTunes billing for users. Picks: Gesture based app selection and organization, Learn Talks. 

EPISODE LINKS

Episode 227 – They’re Everywhere! They’re Everywhere!

We fact check on CSIS, overtime hockey, defeating Face ID, and git commit –amend. #askMTJC brings up promo codes for IAP and the bands on the Stanley Cup. Apple stock sees its best performance in five years. The main topic is top paying tech companies in 2018 and comparative compensation vs cost of living. We review the highlights of the More Than Just Code podcast in 2018. We also choose our top picks for 2018. Picks: Google Home Alone. After Show: The physics MP3 compression and Boxing Day.

Episode 227 Show Links:

Episode 227 Picks:

Keep in touch