Steve Jobs resigns
Although I knew that Steve Jobs would have to step down soon after he announced taking medical leave earlier this year, it is still sad to hear he has now decided to resign the post of Apple CEO.
Rarely can individuals be both as visionary and successful in achieving their vision as Steve Jobs has been.
Any flaws of his character, of which many people seem to know so much, only underline his humanity.
Steve, thank you for sharing the vision of what computing can be with us through the market.
You have inspired many more than you have angered (jealousy is a human flaw after all), and thanks to that sharing I am sure many more good things will follow from Apple and others.
Happy 2011 Geek Pride Day!
In this 2011 Geek Day, I take price in copying and pasting the Geek Manifesto from Wikipedia. Happy Geek Pride Day to all my fellow geeks!
(Republished without permission from http://en.wikipedia.org/wiki/Geek_Pride_Day)
Rights:
- The right to be even geekier.
- The right to not leave your house.
- The right to not like football or any other sport.
- The right to associate with other nerds.
- The right to have few friends (or none at all).
- The right to have as many geeky friends as you want.
- The right to be out of style.
- The right to be overweight and near-sighted.
- The right to show off your geekiness.
- The right to take over the world.
Responsibilities:
- Be a geek, no matter what.
- Try to be nerdier than anyone else.
- If there is a discussion about something geeky, you must give your opinion.
- To save and protect all geeky material.
- Do everything you can to show off geeky stuff as a "museum of geekiness."
- Don't be a generalized geek. You must specialize in something.
- Attend every nerdy movie on opening night and buy every geeky book before anyone else.
- Wait in line on every opening night. If you can go in costume or at least with a related T-shirt, all the better.
- Don’t waste your time on anything not related to geekdom.
- Try to take over the world!
Xcode ad-hock provisioning certificate pains.
In a previous article, http://blog.futureshock-ed.com/2011/01/ios-ad-hock-app-distribution-for-beta...., I documented how I managed to produce a testing version iOS app that I needed to distribute to testers. To do this, I needed to create a ad-hock provisioning certificate on Apple's Developer's Provisioning Portal.
While the method I described worked back then, and I thought I had a decent undersrtanding of the certificate creation and application signing process, when I tried to repeat it last week, it all fell apart.
I tried Xcode 3, Xcode 4, deleting and creating all certificates, editing the Xcode project configuration by text editor, and repeating everything hundeds of times over two days, the bloody thing didn't want to work. I kept getting errors like:
- Code Sign error: Provisioning profile can't be found
- Code Sign error: Provisioning profile '2B29F6DB-B03A-4882-A405-40BB6A2377EC' can't be found
- XCode could not find a valid private-key/certificate pair for this profile in your keychain.
- profile doesn’t match Application Identifier xyz
and many others.
I finally started suspecting that I was innocent of incompetence, and that there was something NOT FUNNY going on with Apple's signing process, especiall the part where in Xcode, you Build and Archive the app, then in the Organizer you Share the archived app by choosing the appropriate code-signing identity.
I decided to find out whether this process really worked.
Reading the documentation (http://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iphone_... discovered that there is a utility that inspects a built application and reports a few interesting statistics and settings, including the certificate used to sign the app.
This utility is called 'codesign'. I tried running it first against the .ipa file that the Organizer creates, but failed. The documentation only had examples with .app files, those produced by the Xcode build process. So I decided to just build the app in Xcode, then browsed to the build directory, and applied the tool to the new .app file. This is what I got:
$ codesign -dvv myApp.app
Executable=/Users/me/programming/iPhone/myApp/build/Beta-iphoneos/myApp.app/myApp
Identifier= myApp.
Format=bundle with Mach-O universal (armv6 armv7)
CodeDirectory v=20100 size=1900 flags=0x0(none) hashes=87+5 location=embedded
Signature size=4337
Authority=iPhone Distribution: Awesome Enterprises Pty Ltd
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=26/03/2011 6:24:21 PM
Info.plist entries=24
Sealed Resources rules=3 files=71
Internal requirements count=1 size=144
That was interesting. The distribution certificate was correct, as specified in my testing profile. This file *should* work if I tried to install it on an iOS device with this certificate installed, as long as the device's UUID was valid for this certificate. With no time wasted, I just drag-droped the .app file onto iTunes; my testing iPod Touch with the correct certificate installed was already connected. Clicked Synced, waited for a few seconds, an there you go, app installed, no worries!
It seems that the Organizer was messing around with the certificates. I don't know exactly how, I might investigate further if time permits, but what was happening just did not make sense for a systemt that one would expect would be throroughly debbuged and working as expected. It seems like this isn't.
So lesson learned: only sign apps in Xcode, forget about archiving in Organizer. Note that the Share Archived Application in the Designer has the option 'Don't Resign". This might produce a properly working archive if in fact it doesn't touch the signing that Xcode did prior to archiving. But with what I have learned about the reliability of all this, I will be staying away from archiving via the Organizer.
HTTP status code symbols for Rails
Thanks to Cody Fauser for this list of HTTP responce codes and their Ruby on Rails symbol mappings. This table is sure to save me a lot of time when I need one of these.
| Status Code | Status Message | Symbol |
|---|---|---|
| 1xx Informational | ||
| 100 | Continue | :continue |
| 101 | Switching Protocols | :switching_protocols |
| 102 | Processing | :processing |
| 2xx Success | ||
| 200 | OK | :ok |
| 201 | Created | :created |
| 202 | Accepted | :accepted |
| 203 | Non-Authoritative Information | :non_authoritative_information |
| 204 | No Content | :no_content |
| 205 | Reset Content | :reset_content |
| 206 | Partial Content | :partial_content |
| 207 | Multi-Status | :multi_status |
| 226 | IM Used | :im_used |
| 3xx Redirection | ||
| 300 | Multiple Choices | :multiple_choices |
| 301 | Moved Permanently | :moved_permanently |
| 302 | Found | :found |
| 303 | See Other | :see_other |
| 304 | Not Modified | :not_modified |
| 305 | Use Proxy | :use_proxy |
| 307 | Temporary Redirect | :temporary_redirect |
| 4xx Client Error | ||
| 400 | Bad Request | :bad_request |
| 401 | Unauthorized | :unauthorized |
| 402 | Payment Required | :payment_required |
| 403 | Forbidden | :forbidden |
| 404 | Not Found | :not_found |
| 405 | Method Not Allowed | :method_not_allowed |
| 406 | Not Acceptable | :not_acceptable |
| 407 | Proxy Authentication Required | :proxy_authentication_required |
| 408 | Request Timeout | :request_timeout |
| 409 | Conflict | :conflict |
| 410 | Gone | :gone |
| 411 | Length Required | :length_required |
| 412 | Precondition Failed | :precondition_failed |
| 413 | Request Entity Too Large | :request_entity_too_large |
| 414 | Request-URI Too Long | :request_uri_too_long |
| 415 | Unsupported Media Type | :unsupported_media_type |
| 416 | Requested Range Not Satisfiable | :requested_range_not_satisfiable |
| 417 | Expectation Failed | :expectation_failed |
| 422 | Unprocessable Entity | :unprocessable_entity |
| 423 | Locked | :locked |
| 424 | Failed Dependency | :failed_dependency |
| 426 | Upgrade Required | :upgrade_required |
| 5xx Server Error | ||
| 500 | Internal Server Error | :internal_server_error |
| 501 | Not Implemented | :not_implemented |
| 502 | Bad Gateway | :bad_gateway |
| 503 | Service Unavailable | :service_unavailable |
| 504 | Gateway Timeout | :gateway_timeout |
| 505 | HTTP Version Not Supported | :http_version_not_supported |
| 507 | Insufficient Storage | :insufficient_storage |
| 510 | Not Extended | :not_extended |
strftime for date/time formating in Ruby - parameters
In Ruby, I often need to format time and date strings to make them look decent. I use strftime, which aparently is used in other languages, like PHP.
In Ruby, you would do something like this:
puts (inspection.date + HOURS_FROM_UTC.hours).strftime('%e-%b-%Y, %H:%M')The formatting parameters (starting with the percentage sign) are many and not to intuitive to remember.
I found one post with a list of most of them here, but I also include them here for quick reference:
%a - abbreviated weekday name according to the current locale
%A - full weekday name according to the current locale
%b - abbreviated month name according to the current locale
%B - full month name according to the current locale
%c - preferred date and time representation for the current locale
%C - century number (the year divided by 100 and truncated to an integer,
range 00 to 99)
%d - day of the month as a decimal number (range 01 to 31)
%D - same as %m/%d/%y
%e - day of the month as a decimal number, a single digit is preceded by
a space (range ' 1' to '31')
%g - like %G, but without the century.
%G - The 4-digit year corresponding to the ISO week number (see %V).
This has the same format and value as %Y, except that if the ISO week
number to the previous or next year, that year is used instead.
%h - same as %b
%H - hour as a decimal number using a 24-hour clock (range 00 to 23)
%I - hour as a decimal number using a 12-hour clock (range 01 to 12)
%j - day of the year as a decimal number (range 001 to 366)
%m - month as a decimal number (range 01 to 12)
%M - minute as a decimal number
%n - newline character
%p - either `am' or `pm' according to the given time value, or the
corresponding strings for the current locale
%r - time in a.m. and p.m. notation
%R - time in 24 hour notation
%S - second as a decimal number
%t - tab character
%T - current time, equal to %H:%M:%S
%u - weekday as a decimal number [1,7], with 1 representing Monday
%U - week number of the current year as a decimal number, starting with
the first Sunday as the first day of the first week
%V - The ISO 8601:1988 week number of the current year as a decimal
number, range 01 to 53, where week 1 is the first week that has at
least 4 days in the current year, and with Monday as the first day
of the week. (Use %G or %g for the year component that corresponds
to the week number for the specified timestamp.)
%W - week number of the current year as a decimal number, starting with
the first Monday as the first day of the first week
%w - day of the week as a decimal, Sunday being 0
%x - preferred date representation for the current locale
without the time
%X - preferred time representation for the current locale
without the date
%y - year as a decimal number without a century (range 00 to 99)
%Y - year as a decimal number including the century
%Z or %z - time zone or name or abbreviation
%% - a literal `%' character
iPhone - Beware of case sensitivity when enabling data model versioning
In an app I'm building, I decided it was about time to start thinking about data model versioning as a way to protect user data from database schema changes. Without versioning, every time I updated the app's schema, the user's data would have to be wiped out. Not good.
Any way, I consulted various sources on how to do this, including my beloved More iPhone 3 Development and Apple's Introduction to Core Data Model Versioning and Data Migration Programming Guide. I made the minor changes to my code in the persistentStoreCoordinator and managedObjectModel, and tested in the Simulator. Great, nothing was broken, the changes worked just as advertised.I continued coding, and a few hours later decided it was time to test on the device.
Bummer, I got this error message: 2011-02-10 14:23:12.470 myApp[9241:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
*** Call stack at first throw:
(
0 CoreFoundation 0x33ac0987 __exceptionPreprocess + 114
1 libobjc.A.dylib 0x3347b49d objc_exception_throw + 24
2 CoreFoundation 0x33ac07c9 +[NSException raise:format:arguments:] + 68
3 CoreFoundation 0x33ac0803 +[NSException raise:format:] + 34
4 Foundation 0x3362b54f -[NSURL(NSURL) initFileURLWithPath:] + 70
5 Foundation 0x33650157 +[NSURL(NSURL) fileURLWithPath:] + 30
6 myApp 0x00003537 -[myAppAppDelegate managedObjectModel] + 138
7 myApp 0x000036fb -[myAppAppDelegate persistentStoreCoordinator] + 302
8 myApp 0x00003407 -[myApp AppDelegate managedObjectContext] + 62
9 myApp 0x0000302f -[iNspectorAppDelegate application:didFinishLaunchingWithOptions:] + 78
10 UIKit 0x3209ebc5 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 772
11 UIKit 0x3209a259 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 272
12 UIKit 0x3206648b -[UIApplication handleEvent:withNewEvent:] + 1114
13 UIKit 0x32065ec9 -[UIApplication sendEvent:] + 44
14 UIKit 0x32065907 _UIApplicationHandleEvent + 5090
15 GraphicsServices 0x33b0ef03 PurpleEventCallback + 666
16 CoreFoundation 0x33a556ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
17 CoreFoundation 0x33a556c3 __CFRunLoopDoSource1 + 166
18 CoreFoundation 0x33a47f7d __CFRunLoopRun + 520
19 CoreFoundation 0x33a47c87 CFRunLoopRunSpecific + 230
20 CoreFoundation 0x33a47b8f CFRunLoopRunInMode + 58
21 UIKit 0x32099309 -[UIApplication _run] + 380
22 UIKit 0x32096e93 UIApplicationMain + 670
23 myApp 0x00002fb3 main + 70
24 myApp 0x00002f68 start + 40
)
Looking at the error trace, something was happening in the managedObjectModel function, and the error message in the first line indicated that the NSURL string was nil. The offending block of code was this: NSString *path = [[NSBundle mainBundle] pathForResource:@"Datamodel" ofType:@"momd"];
NSLog(@"path: %@", path);
NSURL *momURL = [NSURL fileURLWithPath:path]; I added the NSLog line to print out the contents of the `path` variable, and discovered that it was not nil when running in the simulator, but nil when running on the device. I went to have a look at the application assets in
/Users/peter/Library/Application Support/iPhone Simulator/4.2/Applications/F2854B27-4750-4DC8-8CB6-A22B036F5DC9\myApp.app
by right-clicking and selecting "Show Package Contents", and noticed that the data model versioning directory was named `DataModel.momd`.
However in my code, the path variable was `Datamodel` (loading a resource of type `momd`), whereas the directory containing the model versions was `DataModel`.
Yeap, this was another case of the simulator and the device behaving differently, this time in how they handle file name cases.
NSString *path = [[NSBundle mainBundle] pathForResource:@"DataModel" ofType:@"momd"]; and ran on the device, it worked.
iOS: ad-hock app distribution for beta testing
I needed to distribute two copies of a new app I'm building to beta testers, and a process Ithough should only take 30 minutes or so, took me half a day.
Apple's iOS Provisional Portal has these instructions (https://developer.apple.com/ios/manage/distribution/distribution.action):1. Create and Download an iOS Distribution Certificate
2. Create and Download an Ad Hoc Distribution Provisioning Profile
3. Build your application with Xcode
4. Share your application file and the Ad Hoc Distribution Provisioning Profile with the owner of each device
5. Recipients of the application will need to drag the application file and Ad Hoc Distribution Provisioning Profile into iTunes, then sync their iPhone, iPad or iPod touch to iTunes to install
Well, that didn't work. Although I was able to produce a built, create a zip archive of the .app file, install it on the beta tester's iTunes (along side the provisional certificate), after syncing the phone I was getting error messages about either the app not being signed, or the entitlements being incorrect.After lots of reading, trial and error, I managed to get a configuration that worked, documented here. Thanks to the many authors who helped out, including:
How to create an Ad-hock distribution
Mongomapper with Rails 3
These are some notes I have taken while creating my first Rails 3 application with MongoDB/Mongomapper as the back end.After installing RVM, Ruby 1.9.2dev, and Rails 3.0.0.beta4, I followed the instructions here to update a bunch of files (assuming you are running MongoDB locally):config/initializers/mongo.rbMongoMapper.connection = Mongo::Connection.new('localhost', 27017)Gemfile:
MongoMapper.database = "#myapp-#{Rails.env}"if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
MongoMapper.connection.connect_to_master if forked
end
end
source 'http://rubygems.org'gem 'rails', '3.0.0.beta4'gem 'mongo_mapper'config/application.rb
gem 'rails3-generators'
(only first 8 lines shown, not change to the rest of the file)
require File.expand_path('../boot', __FILE__)#require "rails/all"require "action_controller/railtie"Then, I went on to create a model, and to do that I used kristianmandrup's rails3-generators gem:
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
sudo gem install rails3-generators
rails generate model Book --skip-migration --orm=mongomapper
Edit this model to contain at least one MongoDB key:
class Book
include MongoMapper::Document key :title, String
key :author, String timestamps! # Validations :::::::::::::::::::::::::::::::::::::::::::::::::::::
# validates_presence_of :attribute # Assocations :::::::::::::::::::::::::::::::::::::::::::::::::::::
# belongs_to :model
# many :model
# one :model # Callbacks :::::::::::::::::::::::::::::::::::::::::::::::::::::::
# before_create :your_model_method
# after_create :your_model_method
# before_update :your_model_method end
We'll need a controller to access the Book model:
rails generate controller BookThis creates an empty controller file. Edit book_controller.rb to look like this:
class BookController < ApplicationControllerCreate a view for this controller and action in app/views/book/index.erb:
def index
@books = Book.all
end
end
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<h1>Books</h1>
<% @books.each do |book| %>
<div class="entry">
<h3><%= book.title %></h3>
</div>
<% end %>
Add the Book routes in the routes.rb file:
Inspector::Application.routes.draw do |map|
resources :books
end
Start the server to see if the application works so far:
rails server
Navigate your browser to http://localhost:3000/books/index. If you get a blank page with "Books" only displayed, then you are doing well, no worries. There are no errors, but also there are no records to display. The easiest/quickest way to add some books at this point is to use the console. Type "rails console", and add a couple of books:
Finally, make sure the rails server is running, and try to access http://localhost:3000/books. If all went well, the two entries we just made will be listed.PS. Good resources on this subject:
book1 = Book.create(:title => "title 1", :author => "author 1")
=> true
book2 = Book.create(:title => "title 2", :author => "author 2")
=> true
http://www.mongodb.org/display/DOCS/MongoDB+Data+Modeling+and+Rails
http://blog.bitzesty.com/mongodb-with-mongomapper-and-ruby-on-rails
MacRuby and CoreData reading and writing
I am working on an iPhone project that uses CoreData. We need to pre-populate the database with a large dataset, for which the data is available on a number of CSV file.- Once you have a data model created on XCode, you need to compile it into a ".mom" file so that the Persistent Store Coordinator can be instantiated with it. This can be done with momc tool that comes with XCode available in /Developer/usr/bin (see gist example).
- The relationship property names are used when you want to retrieve records, and the attribute property names for saving data.
- In a one-many relationship, the object returned is an Array, through which you can iterate in Ruby with the "each" iterator.
- In a one-one relationship, just use the entity name and its attribute property name.

