Will Apple ever sell me another laptop?

My first laptop was an AT&T Safari running Windows 3.1 that I bought using my employee discount in 1993. It was fine for spreadsheets and word processing but was woefully underpowered for running Photoshop or Director. Even the games that I wrote at the time were barely able to run on it. So my main computer for many years was a desktop. Usually it was the second most powerful Apple computer that Apple sold. And I replaced it every 18 months or so. In July of 2000 I got an Apple G3 laptop that was capable of doing real work. It lasted a bit longer than my typical desktop and was used for testing games for at least 10 years. It still ran, albeit too slow to browse the current internet, when I recycled it a few months ago. After that I used a couple of G4 laptops and handed them down when newer models came out that were significantly faster. I bought my last laptop in June of 2006 and have been happily developing web pages, Director programs, and apps with it. It runs Photoshop and Flash fine and I’d still be using it if I didn’t need a computer that runs Mountain Lion. I briefly borrowed a newer Apple laptop and I am now using a Mac mini. I can’t really tell much difference in the speed compared to my almost 7 year old laptop. The biggest difference is the hard drive. I upgraded my laptop to a 500 GB drive a few years ago and I’m using most of it. The mini has a terabyte drive and it’s nice to have the extra space.

So why did I buy a Mac mini when I’ve been happily using laptops for years? Three reasons. I work at home and at the office, so I need to have the same data in both places. I don’t go into the office as often now but when I do, I can unplug the mini and take it with me. The second reason I liked my laptop was because I used it to look stuff up when reading, watching TV, gardening, etc. But now I have an iPad Mini and an iPod Touch so I don’t use the laptop the same way I used to. All of the information I need can be found with the iDevices. Plus they are much more portable than the laptop. The iPad Mini also lets me watch iTunes University courses and from time to time Netflix.

But probably the deciding factor was performance and price. The Mac mini was $864 including tax. I already have a couple of monitors. The big Samsung is great for coding and the smaller ViewSonic holds mail, files, and miscellaneous code just fine. It has great color fidelity for the times when I need to edit photos. The Mac mini comes with two video ports and an HDMI to DVI Adapter cable, so I connected the Samsung to the HDMI port with the adapter and the ViewSonic to the mini-Display port with my current adapter. It has four USB ports, which aren’t nearly enough on their own, but with a couple of 4 port dongles I could connect my iDevices, Logitech Mouse, and Dell QuietKey keyboard. Two backup hard drives remain behind my big monitor.

I added a Jawbone JAMBOX to get better sound. Since that’s the main selling point of my apps, I need to be able to hear things well. But it was only $164. And that’s all the extra stuff I had to buy.

So for $1,028 I got a 2.3GHz quad-core Intel Core i7, 4GB RAM (expandable to 16 GB for $168 from Crucial if I need to) and a 1TB hard drive. The same specs in a laptop are $2,160. For me, that’s a significant difference. I suppose if I worked at client locations or coffee shops, I’d need laptop. But, since I don’t, it seems like a waste of money to me. Even the lower spec laptop at $1,620 is almost twice what I spent on the Mac mini.

I’ve been using this setup for a month now and it works really well. About the only thing I need to change is to organize the rat’s nest of cables behind the monitor.

Desk

Update: As of April 2015 I still don’t need the extra RAM. And I did fix the rat’s nest of cables as I describe in this post.

Update: Summer 2016. My laptop is still going strong, but my wife’s 2009 MacBook is starting to have problems with the trackpad and is a bit slow for editing photos. I considered getting her a Mac Mini, but she works in a variety of places so she needs a laptop. I like the retina display on the MacBook Pros, but they haven’t been refreshed for four years. The MacBook on the other hand just came out. It is light and much smaller than the MacBook it replaces. Speed hasn’t been a problem and she is getting used to using Pixelmator and Acorn, so she doesn’t miss Photoshop. If I need a laptop, We got the low-end model and it works just fine—especially compared to the old one. As a bonus, it plays Netflix and other video sites fine.

Backups

Backup

It’s amazing how many files you can create when developing software. I had backups scattered over several disks and CDs and recently cleaned everything up. This is the backup of my backup.

I upgraded to a Mac Mini and just use my laptop for accounting and my database since the programs are too old to run on Mountain Lion. I got a little scare though when my laptop wouldn’t boot up. Turns out the battery was so far gone that it wouldn’t even hold enough charge to start the computer. Since I wasn’t using the computer for daily work, I got out of the habit of backing it up so the last backup was a couple of months old. I picked up a cheap ($12) 10GB USB stick for backup. Then I decided to make a second copy of the data on my computer. This one goes to the office so I’ll have a recent backup in case something happens to the computer and the backup in the house.

I also have a git repository for the apps that I’m writing and it gets updated every day. Worst case there is that I lose a couple of hours of work.

ImageOptim

in a previous post I discussed using ImageOptim to reduce file sizes for websites. I also tried it on some apps. Our apps use lots of images and sounds so they are quite large. The table shows the reduction in size when I used ImageOptim and turned off PNG compression in Xcode. You need to turn off PNG compression because Apple uses their own compression method that is supposed to optimize display time but has a side effect of making file sizes larger. I don’t see any difference in display time, so I’ve opted for smaller file sizes.

 
Title
Original Size (MB) With ImageOptim % Reduction
Show Me…CNS  9.104  7.739 15%
Minimal Pairs 16.723 15.090 10%
Show Me… 38.205 29.682 22%

Disable copy in UIWebView

Great answer from Zubaba at Stackoverflow. I’m using a webView to display colored and bolded text and I had the same problem. I put his solution into a method and call it just after I initialize the webView. I don’t seem to need the delegate.


// This is the end of the method where I initialize the web view
    self.textView = [[UIWebView alloc] initWithFrame:textFrame];
    [self longPress:self.textView];

// This is the method that I added
- (void)longPress:(UIView *)webView {    
    UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress)];
    
// Making sure the allowable movement isn't too narrow
    longPress.allowableMovement=100; 
// This is important - the duration must be long enough to allow taps but not longer than the period in which the scroll view opens the magnifying glass
    longPress.minimumPressDuration=0.3;

    longPress.delaysTouchesBegan=YES;
    longPress.delaysTouchesEnded=YES;
    
    longPress.cancelsTouchesInView=YES; // That's when we tell the gesture recognizer to block the gestures we want
    
    [webView addGestureRecognizer:longPress]; // Add the gesture recognizer to the view and scroll view then release
    [webView addGestureRecognizer:longPress];
}

// I just need this for the selector in the gesture recognizer.
- (void)handleLongPress {
        
}

Turning the complier up to 11

I was tracking down a crash caused by memory not being released and I thought it would be helpful to turn on all the compiler options, thinking that maybe it would point to something I did wrong. It didn’t help, but it did generate around a thousand warnings. Only two were actual bugs in the code. Most of the rest were conversion warnings. The most common were defining variables as NSInteger when the method that used them was expecting a CGFloat. Second most common were things like this:


return [[[self fetchedResultsControllerForTableView:tableView] sections] count];

ObjectAtIndex is an unsigned integer so and count is an NSInteger so to get rid of the warning I just cast count to NSUInteger.

return [[[[self fetchedResultsControllerForTableView:tableView] sections] objectAtIndex:(NSUInteger)section] name];

And this


return [[[[self fetchedResultsControllerForTableView:tableView] sections] objectAtIndex:section] numberOfObjects];

which should return an NSInteger rather than an unsigned NSUInteger so here I cast the return value.


 return (NSInteger)[[[[self fetchedResultsControllerForTableView:tableView] sections] objectAtIndex:(NSUInteger)section] numberOfObjects];

Second most common warnings were for unused variables. Since I use the same code for 18 different games I have if statements that determine what the locations of buttons on the screen. Many of the buttons are not used in all of the games so the compiler gives an unused variable warning. To get rid of the warning, I use this line after the last redefinition of the variable. Just so I remember that I’m using it I put it just before I use the “unused” variable. The compiler still compiles correctly when the button is needed, it just doesn’t throw the warning.


  #pragma unused(showHideButtonX)
  #pragma unused(showHideButtonY)
  if ( DISPLAY_SHOWHIDE_BUTTON ) {
      CGRect showHideFrame = CGRectMake(showHideButtonX, showHideButtonY, buttonsSize, buttonsSize);