Another OS X calendar quirk

Posted in Apple, Problems, Software on December 16th, 2014 by michael

angry-computeruserOkay, it just keeps getting weirder for me with Calendar.app in OS X. I created a calendar event just now and wanted to include the restaurant’s name, address, and phone number in the “Location” tab. When I enter that information into the Location box, the app pops up a suggested address that’s identical to mine, but doesn’t include the restaurant’s name or phone number, which I want there. When I click outside of the box to dismiss it, the app deletes my entry and puts in its own “suggested” data.

The only way I can get it to keep what I want there is to tab out of the field. If I subsequently click in that field (ever!), it changes it again.

Now, I love Apple products, and they usually do things well. But dammit, if I want to put additional text into the Location box for an appointment I have, Apple has absolutely no business forcing a change there. None.

Unacceptable, Apple.

Flaky iOS camera behavior

Posted in Apple, Problems, Software on December 9th, 2014 by michael

Photographer1850s

I’ve been getting an unrepeatable error with both my iPhone and iPad under iOS 8. The Camera app’s shutter sound doesn’t work on the first photograph. It doesn’t happen all the time, but it’s frequent enough that it’s noticeable. When I take a second photo, the sound is there.

I just tried to duplicate the problem with the Camera app started cold and again with it brought up from the background, and the sound worked great. I have no idea how to get it to repeat, but I swear I’m not going crazy!

I did a quick web search and couldn’t find any reference to this issue. Has this happened to you?

OS X Calendar app quirk discovered!

Posted in Apple, Problems, Software on March 26th, 2014 by michael

I just added an appointment to OS X’s Calendar app. It’s supposed to run from 10:00 AM until noon. I go to the app and double-click on a date, fill in the event description and location, and then click on the date/time and get this:

Screen Shot 2014-03-26 at 5.09.06 PM

From the keyboard, I enter 10:00 AM as the starting time. Then I tab to the next line and try to enter 12:00 PM as the ending time. It won’t enter that time. It enters it as 10:00 PM, after which I have to go back and manually change it:

Screen Shot 2014-03-26 at 5.11.35 PM

In fact, it won’t let me type anything in the Hours space other than 11 until after I’ve changed the AM/PM indicator first. Now, I know I could do that and I know I could click on the time and select from Apple’s pre-ordained choices (from 30 minutes to 3 hours in half-hour increments). But what if I just want to type in an ending time? Don’t you think Apple’s programmers would automatically allow meetings to go past the noon/midnight barriers?

Am I the only one to discover this issue?

Terrible Connectors

Posted in Hardware on December 9th, 2013 by michael

 

5pin180dinplugAm I the only one who hates those new Lightning iPhone/iPad connectors?

Yeah, I know they’re way better than the old 30-pin connectors. They can be plugged in either way, they’re small, they’re new, they have special Apple-y goodness, etc.

But there’s a problem anyway. The socket is absolutely impossible to find on my iPad without holding the thing edgewise and finding it.  With the old 30-pins, you could just feel your way to it and then plug it in. If you had the plug upside down, that was readily apparent and you simply turned it over.

Dare I say . . . it just worked?

The Open Sign

Posted in Computer Science on November 2nd, 2013 by michael

Fire Open

My wife and I went to Costco this morning, like most American couples do every Saturday. While we were there, I noticed a really cool “Open” sign. It flashes and does who knows what else. Mostly, I suspect it says “Open” in a very bright fashion.

I’ve been having a bit of trouble concentrating on business for the past nine months or so. Coincidentally, I’ve been self-employed for the past nine months or so. I find it comically easy to get distracted by, well, pretty much anything. And I find it frustratingly difficult to get back on task.

For example, I spent the entire day yesterday configuring Moe, my Mac Mini Plex server for the house. I copied a couple thousand songs from Curly, my trusty laptop over to Moe. Then I discovered I needed to configure the metadata, including embedded artwork for almost all of them. Found a free tool called Tagr that makes it easy. Highly recommended.

But that took hours and hours to get accomplished. Sure, now I can stream my own music library (at least the parts of it I actually like – why do I have so much music I don’t like? – am I the only one with thousands of songs in my music library that I never listen to?) to all the TVs in the house, but I got zero work accomplished yesterday.

On the one hand, I tell myself that’s the advantage of being self-employed. I can take a day off when I feel like it. But I guess I’m just a mean boss because I feel kind of bad about it the whole time. Stop nagging me, me!

Anyway, back to the “Open” sign. I figure I could buy it, put it in my office, and turn it on when I want to work. The flashing blue and red LEDs would remind me to keep my nose to the grindstone, my shoulder to the wheel, my ear to the tracks, and my eye on the ball. Kind of a difficult position to work in, but you know. An additional advantage to the sign would be that it would serve as an advisory to my wife and son that the brain is engaged. Not that it would stop wife from asking for help on her own projects – she’s battling a long-term illness and needs more help than she did before or will in the future. But it would serve as an advisory.

Plus, the bright lights might help keep me awake during my daily 2:00 slump. Seriously, I cannot stay awake at 2:00 PM. The strange thing is that my body somehow knows when it’s Daylight Savings Time and still falls asleep precisely at 2:00 PM. Don’t hate me.

apple

Speaking of Plex, I’ve been finally trying to get out of the iTunes/Apple TV ecosystem for my home video and audio services. I have a couple of very nice Roku players, including a super-cool Roku 3 in my living room. The other one covers the TV in my bedroom. All that was left was the TV in the office, which is still hooked up to my 2G Apple TV. The problem with this arrangement is that I still had to keep all the audio and video files in iTunes on Moe. The Rokus don’t demand that, but that one Apple TV certainly does. I had an old 1G Apple TV lying around the house doing nothing, so I decided to see if I could figure out a way to make it run Plex.

I couldn’t. But I did find an excellent solution that puts XBMC on the Apple TV, and it plays very well with the XBMC server on Moe. So that’s what I did. It’s called OpenELEC – Embedded Linux Entertainment Center – and it’s working great. I no longer have to keep iTunes running on Moe and I no longer have to add all my files to its increasingly horrible and slow interface. I swear, iTunes takes a minute or so per file just to set up the metadata that puts TV shows in the TV show section and movies in the Movie section. Before that, they all get imported as Home Movies. I’m not going to miss iTunes on Moe. Not one little bit.

atv-bootloader

Anyway. ELEC on Apple TV 1G is highly recommended. The machine has way more power than its native interface allows it to use. It can play pretty much any video file beautifully. Try it out.

Back to work.

iTunes annoyance

Posted in Apple, Computer Science, Software on October 6th, 2013 by michael

05_Flatbed_2 - SEPTEMBER

Am I the only one who’s sick of the changes Apple keeps making to iTunes? It worked well before. Now it doesn’t.

The latest: they’ve eliminated the forward and back buttons from the Get Info window. Why did they do that? Those buttons weren’t hurting anybody.

I often want to edit multiple files’ information. I used to open the first one, edit it, and press the forward button to edit the next file. That worked okay, even after they changed it from a quick operation to a painfully slow one with iTunes 10 (or was it 9?). Now I have to open each file’s Get Info panel separately, taking about twice as long as the already painfully slow previous version.

Why did you do that, Apple?

Implementing preferences in iOS – the right way

Posted in Computer Science, Morse Trainer on August 25th, 2013 by michael

Douglas_Groce_CorriganA few weeks ago, I shared how I implemented preferences in my Morse Trainer appthe wrong way. Since then, I’ve learned, and I present here a brief synopsis on how to do preferences the right way.

I’m getting ready to update the app. I’ll be taking out the tabbed view and giving access to the preferences/about page via a button. While I expect the Settings page itself to look pretty much the same as before, the insternal storage location of the two settings – code sending speed and text source – will move from a user-space simple file to the User Defaults system. In the transition, the code will get a bit less complex.

Looking back at the old code, I see it’s not really as bad as I thought. At least I’m using using a keyed archive data structure. Let’s see how we can clean this up a bit, though.

Here’s how we’d rewrite last time’s code snippets.

What we did before:

- (void)viewWillAppear:(BOOL)animated {
   [super viewWillAppear:animated];
   .
   .
   .
   // Get the current stored preferences
   // Get the full path of our preferences data archive file
   NSString *prefsDataPath = [self preferencesDataPath];
   // Attempt to unarchive it
   PreferencesData *preferencesData = [NSKeyedUnarchiver
   unarchiveObjectWithFile:prefsDataPath];
   // If it didn't exist, set it to defaults
   if (!preferencesData)
   {
      // Set to the default data
      sendSpeed = 2; // fast
      textSource = 0; // quotes
   }
   else
   {
      sendSpeed = [preferencesData sendSpeed];
      textSource = [preferencesData textSource];
   }
   .
   .
   .
}

And what we do now:

- (void)viewWillAppear:(BOOL)animated {
   [super viewWillAppear:animated];
   .
   .
   .
   sendSpeed = [[NSUserDefaults standardUserDefaults] stringForKey:@"sendSpeed"];
   textSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"textSource"]
   // If there's not already data there, the system will return nil, so we set it here
   if (sendSpeed == nil)
      sendSpeed = 2; // fast
   if (textSource == nil)
      textSource = 0; // quotes
   .
   .
   .
}

When it’s time to save, here’s what we did:

-(IBAction) sourceControlIndexChanged {
   textSource = self.sourceControl.selectedSegmentIndex;
   // Save the current preferences data to disk
   PreferencesData *preferencesData = [[PreferencesData alloc] init];
   [preferencesData setTextSource:textSource];
   [preferencesData setSendSpeed:sendSpeed];
   // Get the full path of our preferences data archive file
   NSString *prefsDataPath = [self preferencesDataPath];
   // Archive the preferences data to file
   [NSKeyedArchiver archiveRootObject:preferencesData toFile:prefsDataPath];
   [preferencesData release];
}

And here’s what we do now:

-(IBAction) sourceControlIndexChanged {
   [[NSUserDefaults standardUserDefaults] setValue:self.sendSpeed forKey:@"sendSpeed"];
   [[NSUserDefaults standardUserDefaults] setValue:self.textSource forKey:@"textSource"];
   [[NSUserDefaults standardUserDefaults] synchronize];
}

So we’ve saved a lot of code and increased understandability, and all by doing it “the right way.”

What have you done “the wrong way” that you’d like to go back and do over?

Photograph of Douglas “Wrong Way” Corrigan courtesy of Wikipedia and sourced from the U.S. Government; as such, it is in the public domain.  I highly recommend the very entertaining Wikipedia article.

Calculating hashes in iOS

Posted in Software on July 27th, 2013 by michael

simulat screenshot

I intended to follow up my last post (Implementing preferences in iOS – the wrong way) with a treatise on how to implement preferences the right way.  Even promised to do it.  But first a brief detour.

I wanted to write a quick demo app to show how to use NSUserDefaults to implement simple preferences.  For that demo, how about something that calculates the MD5 hash of an NSString?  We’ll call it Hasher.  Should be quick and easy, and I need the tech for the project I’m currently working on.  Did a little bit of searching and discovered that Apple provides a C library called Common Crypto.

But I’d rather code in pure Objective C.  A little more searching led me to Matt Gallagher’s excellent Cocoa with Love website and his HashValue wrapper class for Common Crypto.  Just the thing!  After a bit of confusion in using that class, which was written in 2009, I searched just a bit more and found Calvin Cestari’s slight updates that were last published in March 2013.  Download his code here.

Matt’s website does a fairly good job describing his code, but there’s nothing about using it.  So let’s put it together and make it run, shall we?

I started out by creating a new iPhone-only single-view application called Hasher.  For this demo, there’s no need to make an iPad version.

Create project

The storyboard is simple: two labels and two text fields.

Storyboard

In HasherViewController.h, I hooked the TextFields up:

@interface HasherViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *plaintext;
@property (weak, nonatomic) IBOutlet UITextField *md5Hash;
@end

And also hooked the plaintext field up to HasherViewController.m:

- (IBAction)calculateHash:(UITextField *)sender
{
}

Next, I unzipped the CCToolkit-master.zip file…

HashValue

…and dragged the two files into my project.  The first time, I forgot to check the “Add to Targets” box.  Don’t follow my bad example there.

DragFilesIn

The API is pretty simple:

+ (HashValue*)MD5HashWithData:(NSData*)data;
+ (HashValue*)SHA256HashWithData:(NSData*)data;

- (id)initWithBuffer:(const void*)buffer hashValueType:(enum HashValueType)aType;
- (id)initMD5HashWithBytes:(const void*)bytes length:(NSUInteger)length;
- (id)initSHA256HashWithBytes:(const void*)bytes length:(NSUInteger)length;

In fact, we only need the two class methods:

MD5HashWithData:data

and

SHA256HashWithData:data

For this example, we’ll only use the MD5 version.  If you’re planning on hashing passwords for real, though, please note that MD5 is considered to be broken.  Use SHA256.  I didn’t use it here because the 64-character hashes are too long to fit in my Text Field.

So we need just three lines of code.  First, we need to convert our NSString* to NSData*:

NSData* data = [self.plaintext.text dataUsingEncoding:NSUTF8StringEncoding];

Next, we simply make the call:

HashValue *hashValueMD5 = [HashValue MD5HashWithData:data];

And finally, we populate the Text Field:

self.md5Hash.text = hashValueMD5.description;

Before these lines, though, a tiny bit of housekeeping:

if ([self.plaintext.text isEqualToString:@""])
{
self.md5Hash.text = @"";
return;
}

I discovered that, after generating a hash and deleting the plaintext, a hash is still created.  So the housekeeping lines above are just for appearance’s sake.

So here’s the entire HasherViewController.m file:

//
//  HasherViewController.m
//  Hasher
//
//  Created by Michael Morrow on 7/27/13.
//  Copyright (c) 2013 Business Casual Software LLC. All rights reserved.
//
//  Permission is given to use this source code file, free of charge, in any
//  project, commercial or otherwise, entirely at your risk, with the condition
//  that any redistribution (in part or whole) of source code must retain
//  this copyright and permission notice. Attribution in compiled projects is
//  appreciated but not required.
//

#import "HasherViewController.h"
#import "HashValue.h"

@interface HasherViewController ()

@end

@implementation HasherViewController

- (IBAction)calculateHash:(UITextField *)sender
{
  // Blank out the results when the string goes away
  if ([self.plaintext.text isEqualToString:@""])
  {
    self.md5Hash.text = @"";
    return;
  }

  // Get and display an MD5 HashValue object
  NSData* data = [self.plaintext.text dataUsingEncoding:NSUTF8StringEncoding];
  HashValue *hashValueMD5 = [HashValue MD5HashWithData:data];
  self.md5Hash.text = hashValueMD5.description;
}

@end

It’s that easy!  Oh, one more thing.  We need to be sure to import the Security framework and the libCommonCrypto library:

Screen Shot 2013-07-27 at 10.45.41 PM

At least I think I needed to import libCommonCrypto.  Maybe I’ll check that out later.

Next time, I’ll expand this project to include preferences.

Download the entire xcode project for this demo here.

Implementing preferences in iOS – the wrong way

Posted in Computer Science, Morse Trainer on July 13th, 2013 by michael

1280px-PAVE_Paws_Computer_Room

It’s not really my fault.  Okay, it is my fault, but I have an excuse.  I was a beginning iOS programmer.  How was I supposed to know?

I’ve been developing software for money since 1985.  In college, we used an IBM 360 mainframe, segued gradually to “mini” computers – a variety of DEC VAXes – and finally got a bit of exposure to the original IBM PC, running MS-DOS.  We learned FORTRAN, Ada, Pascal, PL/1, Prolog, C, and assembly language and had a tiny bit of exposure to Unix.

When I got to industry, it was back to the mainframe.  I developed flight software for the Atlas launch vehicle and its Centaur upper stage.  It was programmed in assembly language and hosted on a CDC Cyber mainframe running a cross-assembler written by us (in FORTRAN!).  The Cyber also hosted our written-in-house linker/loader/simulator.  It was a pretty slick setup for the time, in spite of non-interactivity of the tools.  We spent a lot of time waiting for printouts.  But there were no punchcards!  Unlike the college mainframe.

As the years went by, we graduated to VAXes and high-level languages (Ada!) and then eventually to Sun workstations and other high-level languages (C++!).  And the flight computers became smaller, lighter, and faster as time went on.  Although space-qualified computers are never going to be particularly small, light, or fast.  My iPhone has way more power than the best flight computer I’ve ever worked on.

But there’s a common element among all those machines and my work on them.  There was no such thing as a GUI.  In all my professional rocket science work, I never wrote a single line of software for a person to use.  Quite a handicap as I transitioned to iOS programming.

So it wasn’t entirely my fault when I wrote my first iOS preferences view.  How do you move from your app’s main view to a preferences view, change defaults, and have them apply to the main view when you get back, and do all this while following the sacred object-oriented religion, not sharing any global data between objects, and making preferences persist between executions of the app?  I finally figured it out –  but I had no idea a couple years ago when I wrote my first app.  But I worked something out.

So how do you do it the wrong way?  The file system.  Every time the Morse Trainer app is launched, it checks for the existence of its preferences file.  If it doesn’t exist, it creates it and puts in default values for its two preferences.  It goes through the same routine when transferring from another view (in this case, the only other view is the preferences setter), ensuring that it always knows the user’s current preferences.  Behold:

- (void)viewWillAppear:(BOOL)animated {
 [super viewWillAppear:animated];
 .
 .
 .
 // Get the current stored preferences
 // Get the full path of our preferences data archive file
 NSString *prefsDataPath = [self preferencesDataPath];
 // Attempt to unarchive it
 PreferencesData *preferencesData = [NSKeyedUnarchiver
   unarchiveObjectWithFile:prefsDataPath];
 // If it didn't exist, set it to defaults
 if (!preferencesData)
 {
    // Set to the default data
    sendSpeed = 2; // fast
    textSource = 0; // quotes
  }
  else
  {
    sendSpeed = [preferencesData sendSpeed];
    textSource = [preferencesData textSource];
  }
  .
  .
  .
}

Pretty much the same thing happens in the settings controller, except that all changes are written to disk immediately, just in case the view is swapped out:

-(IBAction) sourceControlIndexChanged
{
  textSource = self.sourceControl.selectedSegmentIndex;

  // Save the current preferences data to disk
  PreferencesData *preferencesData = [[PreferencesData alloc] init];
  [preferencesData setTextSource:textSource];
  [preferencesData setSendSpeed:sendSpeed];

  // Get the full path of our preferences data archive file
  NSString *prefsDataPath = [self preferencesDataPath];
  // Archive the preferences data to file
  [NSKeyedArchiver archiveRootObject:preferencesData
    toFile:prefsDataPath];
  [preferencesData release];
}

And how did I implement the Settings view?  A tab view controller.  Sheesh.  I don’t think I could have done it any more awkwardly.  All I needed to do was push the Settings view controller via a button or something and pop it back off when I was done with it.  But that never occurred to me.  And the Apple reviewers let me get away with it, so I guess it wasn’t too terribly abnormal.

I didn’t know about passing information back and forth between controllers (prepareForSegue in the forward direction and delegation for going back).  So I guess I did the best I could at the time.

I’m about to start a rewrite of the app to add a whole bunch of new content – see this post for a partial shopping list – and I’ll redo both the data storage/retrieval setup as well as how the inter-view navigation takes place.  Watch this space for details on how I’ll do it The Right Way.

Trouble with Evernote

Posted in Computer Science on June 17th, 2013 by michael

Angry_elephant_ears

I love Evernote. It’s the perfect cross-platform organizer. It sucks in everything I’ve given it, allows me to index my data, has great search capability, and works on everything electronic I own. Granted, all I really use it for is note taking, but I’m gradually expanding. For example, I think I’ll add all my business receipts in the near future. That will make them much more easily searchable and allow me to just take photos and upload them; even the text in the photos will be searchable.

But a very dark cloud just loomed over my Evernote-loving horizon.

I still use my trusty old first-gen iPad. It’s gotten a bit clunky and crashy in some instances – especially with the Safari and Chrome web browsers and even more with Feedly’s built-in browser. But it’s still otherwise pretty stable and usable. In fact, I’m using the greatly-improved WordPress app to write this post and everything is working fine.

That’s why I was absolutely dismayed this morning when Evernote for iPad failed in the most spectacular way possible. I was editing a note containing this website’s editorial calendar (time to step up my game) and needed to copy and paste a couple of lines. I did so and the entire note just . . . disappeared. Everything but the first line. Hit the Undo button and . . . nothing changed. My note was gone. The iOS app doesn’t seem to have access to older versions of notes, so I couldn’t restore. In fact, I’m not a premium user, so I can’t restore anyway. Besides, the premium restore feature doesn’t save versions anyway. Just an occasional backup. Granted, that’s better than nothing, which is what I currently have.

Luckily, I was able to quickly solve the problem. The place we’re currently staying has horribly slow wifi, so I quickly closed the app on my iPad before it had a chance to sync, opened the app on my iPhone, copied the entire text of the note, and emailed it to myself. When I reopened the app on the iPad, the note synced and deleted all the text from the server. I copied and pasted it back in from the email and deleted the duplicated first line, and I’m back in business.

In the link quoted above, the original poster was also able to recover his text by digging around on the laptop he was using, but I don’t think that’s possible on my iPad. Well, maybe I could’ve synced the iPad with my computer and then dug around in the copied data. I don’t know if that would work and I’m pretty sure it would be frustrating, so I’m thanking my lucky stars for slow Internet connections.

Have you found a better way to preserve deleted data? More importantly, has your iOS-based version of Evernote disappeared your data? That’s a problem that’s so fundamental – if I can’t trust it not to delete critical data at random – I’m now having serious second thoughts about using it at all. How about you?

This image was originally posted to Flickr by Mister-E at http://flickr.com/photos/45189308@N00/2247141772. It was reviewed on 10 November 2012 by theFlickreviewR robot and was confirmed to be licensed under the terms of the cc-by-2.0.