Archive for January, 2009

iPhone Programming: Adding a Contact to the iPhone Address Book - January 28, 2009 at 8:09 am

 

Adding a contact to the iPhone’s address book isn’t horribly complicated, but it’s not the most straightforward process in the world, either, because the documentation leaves a bit to be desired. There is an Address Book Programming Guide published by Apple, but at 28 pages, it feels a bit bloated when you’re just trying to quickly figure out a simple process like this, and somewhat ironically, the "Creating a New Person" section is less than a page, and doesn’t go into much detail. The XCode documentation is helpful, but it still takes some effort to put all the pieces together, so this is basically just a walk-through of the process of creating a new contact, and adding some common fields to it.

To create a new record, we start out by creating a CFErrorRef variable that will hold any errors that get generated throughout the rest of the process. In my experience, most errors here tend to generate exceptions anyway, but there’s an error parameter, so we may as well use it. Anyway, here’s the line: 

        CFErrorRef error = NULL; 

We then create our reference to the iPhone Address Book with a call to ABAddressBookCreate():

        ABAddressBookRef iPhoneAddressBook = ABAddressBookCreate();

And then we create a new person record:

        ABRecordRef newPerson = ABPersonCreate();
 

At this point, we haven’t saved anything to the address book yet, but we can start adding data to the person record. To do this, we use ABRecordSetValue, but some fields need to be formatted differently from others. For some, like first name and last name, we can just pass in a string:

        ABRecordSetValue(newPerson, kABPersonFirstNameProperty, @"John", &error);
        ABRecordSetValue(newPerson, kABPersonLastNameProperty, @"Doe", &error);

kABPersonFirstNameProperty and kABPersonLastNameProperty are constants defined by Apple that specify which fields you’re saving. They’re listed in the XCode documentation under Personal Information Properties in the ABPerson Reference document. We can also set some other fields in this manner, such as company and title:

        ABRecordSetValue(newPerson, kABPersonOrganizationProperty, @"Model Metrics", &error);
        ABRecordSetValue(newPerson, kABPersonJobTitleProperty, @"Senior Slacker", &error);

Where it gets a bit trickier is when we want to set our phone, email, or address properties, because these fields use ABMutableMultiValueRef rather than strings to store the data, and the specific data types of the values vary a bit depending on which one we’re talking about. For phone, we would do something like this:

 
        ABMutableMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
        ABMultiValueAddValueAndLabel(multiPhone, @"1-555-555-5555", kABPersonPhoneMainLabel, NULL);
        ABMultiValueAddValueAndLabel(multiPhone, @"1-123-456-7890", kABPersonPhoneMobileLabel, NULL);            
        ABMultiValueAddValueAndLabel(multiPhone, @"1-987-654-3210", kABOtherLabel, NULL);        
        ABRecordSetValue(newPerson, kABPersonPhoneProperty, multiPhone,nil);
        CFRelease(multiPhone);
       

 The first two phone types (kABPersonPhoneMainLabel and kABPersonPhoneMobileLabel) are listed as Phone Number Properties in the ABPerson Reference, along with kABPersonPhoneHomeFAXLabel, kABPersonPhoneWorkFAXLabel, and kABPersonPhonePagerLabel. Despite the fact that the two fax numbers and the pager number seem fairly useless (you can’t send a fax from your phone, and who has a pager anymore?) but there’s nothing listed there for Other, or Work Phone or anything like that. That’s where the Generic Property labels come into play:

      kABWorkLabel;
      kABHomeLabel;
      kABOtherLabel;

Those will file the phone numbers as Work, Home, and Other, respectively. After adding the values to the ABMutableMultiValueRef, we need to call ABRecordSetValue, only this time instead of passing a string in for the third parameter, we pass in multiPhone. Then be sure to free up the memory with CFRelease.

Adding email addresses to the record is pretty similar to adding phone numbers, where we create an ABMutableMultiValueRef of strings:

        ABMutableMultiValueRef multiEmail = ABMultiValueCreateMutable(kABMultiStringPropertyType);
        ABMultiValueAddValueAndLabel(multiEmail, @"johndoe@modelmetrics.com", kABWorkLabel, NULL);
        ABRecordSetValue(newPerson, kABPersonEmailProperty, multiEmail, &error);
        CFRelease(multiEmail);

Where it gets a little different is when we go to set the street address values. While we do still use an ABMutableMultiValueRef, we won’t be using kABMultiStringPropertyType. To set the street address, we use kABMultiDictionaryPropertyType instead, so we have to create an NSMutableDictionary, and the method calls end up being a bit different:

            ABMutableMultiValueRef multiAddress = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
           
            NSMutableDictionary *addressDictionary = [[NSMutableDictionary alloc] init];

            [addressDictionary setObject:@"750 North Orleans Street, Ste 601" forKey:(NSString *) kABPersonAddressStreetKey];
            [addressDictionary setObject:@"Chicago" forKey:(NSString *)kABPersonAddressCityKey];
            [addressDictionary setObject:@"IL" forKey:(NSString *)kABPersonAddressStateKey];
            [addressDictionary setObject:@"60654" forKey:(NSString *)kABPersonAddressZIPKey];

            ABMultiValueAddValueAndLabel(multiAddress, addressDictionary, kABWorkLabel, NULL);
            ABRecordSetValue(newPerson, kABPersonAddressProperty, multiAddress,&error);
            CFRelease(multiAddress);

kABWorkLabel means that we’re setting this as the contact’s work address. And to add it to the contact record, we call ABRecordSetValue as before, releasing the memory afterward.

 The last step is to add the new record to the address book, and save it back to the device:

        ABAddressBookAddRecord(iPhoneAddressBook, newPerson, &error);
        ABAddressBookSave(iPhoneAddressBook, &error);

And then we can check for any errors:

        if (error != NULL)
        {

                  NSLog(@"Danger Will Robinson! Danger!");

        }

 

So that concludes this introduction to creating new records in the address book.

Tom

Who should Optimize their salesforce.com? - January 26, 2009 at 7:06 am

Optimization

If 2009 is the year to do more with what you have, then optimizing your salesforce.com configuration should be one of your top priorities.

Model Metrics has helped scores of companies to “optimize” what they accomplish with salesforce.com. To be clear, optimization clients are existing subscribers of salesforce.com whom Model Metrics did not initially implement. It is interesting to see both the state in which these saleforce.com subscribers come to us, as well as the results once their optimization has been completed.

How do you know if you should optimize? Here are five profiles we often see:

1. Some of our optimization clients implemented salesforce.com and never moved past the core CRM fundamentals – contact management and pipeline management for example. Lots of room for improvement here obviously.

2. Some optimization clients did not make efforts to align their CRM configuration and usage with their company’s goals and strategies. This limit’s the ability to impact results and often leads to low rates of adoption among frustrated users who feel their CRM efforts are wasted.

3. Some optimization clients did not define initial goals and objectives. The result here is no way to evaluate success or readiness to raise the bar to higher-level initiatives, a step that increases ROI on CRM.

4. And some optimization clients never took ownership of their salesforce.com solution by having a trained salesforce.com administrator role to monitor usage, solicit feedback, make configuration updates, provide ongoing user training, and stay on top of the constantly evolving new features that can improve business processes or support other groups of users to improve collaboration, customer experience, and other goals.

5. The most common reason companies optimize is that they did not approach CRM with a complete solution plan – strategy, change management, ease of use, reports and dashboards, integration, training, AppExchange utilities, governance, administration, etc.

In future posts I’ll share details about actual optimizations and the results they achieve.

If you have questions or ideas related to salesforce.com optimization that you would like to share, please feel free to contact me at kturner@modelmetrics.com.

Lessons for the Beginning iPhone Developer - January 23, 2009 at 9:57 am

Getting started with iPhone development can be an intense process. If you’re not coming from the world of OSX development, you’re probably more familiar with the myriad languages that look more like C++ than Smalltalk, and you have a lot of new syntactical things to learn, with square-brackets in abundance. It can be easy to focus completely on learning the syntax of Objective-C, and forget that the iPhone is a device with more severe limits on resources than computers, and that you will ultimately have to get your app approved by Apple before you can distribute it, so you need to follow their guidelines to the letter.

Following are some lessons indented for developers who are well versed in any number of other programming languages, but who are coming to the iPhone for the first time.

Memory Management

This one is huge, and easy to underestimate. Don’t develop your entire application and then decide to check to see if you have any memory problems. The iPhone has about 128 MB of volatile memory on board, and the virtual memory model does not include swap space. This means that, even though your iPhone has 8GB or 16GB of Flash storage, memory that your application allocates will not be swapped out to the disk to free up system memory. Since over-releasing objects will crash an application in often difficult to understand ways, it can be tempting to never release objects. However, the system monitors memory usage, and shuts down any application that takes up too much memory. This is the cause of a great many application crashes on the iPhone. You can use around 30 MB safely. Get closer to 40 or 50, and the system will very likely shut your app down with an exit status of 101.

Technically speaking, the system monitors total memory usage in order to maintain continuity of critical applications, such as the phone system, the audio system, and other systems that run constantly on the phone. When total memory usage climbs high enough that the functionality of these systems is put in jeopardy, the application currently on top of the stack will be shut down. This does mean that it is possible for one of these background processes to be using too much memory, causing your app to be shut down. Shutting down the phone and restarting usually takes care of these sorts of conditions.

Definitely read and understand the Memory Management Programming Guide for Cocoa, it’s one of the most important documents to read.

Generally, the Memory Management guide can be summed up by saying that you must release any object that you create with alloc, new, or copy, or one that you have specifically retained with retain.

Human Interface Guidelines

Read and understand the Apple Human Interface Guidelines. Apple calls this document “required reading” for a reason. They’re not being allegorical. Failure to follow the guidelines has resulted in many apps being rejected from the app store. You can always resubmit, of course, but resubmitting means you’ll have to wait for your app to be approved again.

Understanding the Review Process

Before you can distribute your app on the App Store, you’ll have to submit the app to Apple for review. This can take anywhere from a few days to…unfortunately…a few months. Most apps will get some sort of response from Apple within a week. These responses fall into three categories:
 

  1. Approved: Hooray! Your app will appear in the App Store shortly.
  2. Rejected: Unless your app has been deemed inappropriate for the app store, you will be given a list of items to fix. Fix them and resubmit for approval.
  3. Unexpected Additional Time to Review: This is bad. iPhone developer forums are full of stories of apps that have gotten this feedback, and have been stuck in the queue for months to follow. It may be a good idea to resubmit your app at this point and hope for another reviewer. I haven’t found any definitive answers on what the best course of action is when this happens.

Exception Breakpoints

By default, exceptions are not very easy to trace in XCode. This is a pain because it makes it impossible to debug application crashes. Luckily, the solution is pretty simple. Adding a global breakpoint for “obj_exception_throw” and “–[NSException raise]” will cause XCode to break on exceptions, allowing the stack trace to be viewed. Global breakpoints can be added in XCode under Run => Show => Breakpoints.

“malloc_error_break” can be used to obtain information on a malloc error.

Zombies!

Over-releasing objects can cause difficult to track down problems, usually resulting in an EXC_BAD_ACCESS exception. Setting the NSZombieEnabled environment variable will dynamically change the class of deallocated objects to _NSZombie rather than actually freeing the memory. This does mean that memory is never freed, so obviously, this isn’t something to be left on all the time, but it can come in handy when trying to track down over-releases and premature releases. NSZombieEnabled is set by editing the Active Executable, and adding an Environment Variable named “NSZombieEnabled” with a value of “YES”.

GDB Console Commands

Debugging in XCode is frustrating until you realize the power of GDB in the console. Set a breakpoint in your code, and you can learn all sorts of things with these commands:

  • print (unsigned int)[someObject retainCount]
    • display the retain count of an object
       
  • print (unsigned int)[[someObject size] retain]
    • Show the size of an object. The retain is necessary to keep the object from being released here.
       
  • po someObject
    • display information about an object. In the case of an NSString, the string will be printed.
       
  • po [someView subviews]
    • Print an array of subviews of a view.

       

 

In the Cloud with SFDC, Amazon, and Barack - January 20, 2009 at 11:30 am

First blog since Dreamforce… not good! The marketing guys are all over me. “You have to blog consistently.” Of course they’re right, but who has the time! Inauguration was yesterday, pretty amazing times. So now that Obama is in and the recession will be coming to an end, banks will become stabilized, the capital markets will bounce back, and general goodness will proliferate throughout the world, it’s time to blog and get ready for a great 2009. Maybe he’ll need a quarter or two…

Anyway, things are moving fast. Salesforce’s year end is approaching at the end of January, so things are crazy. A million deals, trying to help the SFDC guys to pull them in. Since Dreamforce, we have seen custom development opportunities on the Force.com platform explode. Some of our customers and prospects are simply looking to add a bit of functionality such as in-line dashboards with the slick Adobe Flex look. Others are extending application functionality to expand the footprint of Salesforce in dramatic ways within their organization. We have seen huge demand for platform applications of all sorts, especially portals, call center applications, and now Salesforce Sites for building websites of top of Salesforce.
Many of these applications leverage Amazon’s new web services as well as Google technologies. The mashing up of all these cloud technologies has definitely arrived and we as a company are really starting to be known as the cloud guys and not just the salesforce guys. Of all the cloud players outside of salesforce, Amazon is definitely the most interesting (no offense to Google, Adobe, Facebook, etc.). Salesforce is the place to start for entry into the cloud, but once in, it’s time to leverage all these other technologies and bring the things they do great back into Salesforce and to the huge benefit of users, customers, or partners.
So what’s cool about Amazon? Roughly 30% of their revenue now comes from outside their core business of selling their own books. We get asked all the time about what they’re doing and how it can be leveraged. Here’s my quick two cents:
  • EC2 – Host your data center on Amazon, leverage it for databases and mail servers, use it as a disaster recovery site, and leverage vast amounts of computing power. This isn’t the most exciting offering to talk about, but you can have access to Amazon’s amazing infrastructure for pennies.
  • S3 – This is what most people think about when they think about Amazon Web Services. This is simply storing documents with Amazon, again, for pennies. You can easily pull images of documents into Salesforce or wherever else, so the user doesn’t even know where it’s located, they just know it’s easy to access and you know that it’s cheap.
  • DevPay and Fulfillment Services – Now we’re getting into some more exciting areas. DevPay enables you to leverage Amazon’s shopping cart and billing system for launching a store. You can even sell subscription plans, not just a fee per order. Fulfillment Services is really interesting. This may not be a true cloud app, but you can actually send Amazon your inventory and they’ll store it in their distribution centers, which of course are the best that money can buy. They handle packing and shipping when someone buys from you, whether from your website or from there’s. You can focus on sales and marketing, they focus on the boring stuff that they do better than anyone else. Very cool!
  • Mechanical Turk – This is definitely my favorite. Amazon calls it artificial artificial intelligence. It’s basically a workforce in the cloud. Some tasks computers just aren’t that great at. So you can send a task up through Amazon to the Turkers and for pennies they’ll complete the task. These are people located all around the world, who, for 2 cents or 5 cents or 1 dollar, depending on the task, will do something you ask of them. It could be looking at an image and transcribing it into data. When Steve Fossett’s plane went down, they leveraged the Turkers to look at satellite maps and help in their search, scanning for the plane. Companies also leverage it to clean data, analyze catalogs and competitive coupons, etc.
Anyway, hopefully it won’t be another two months and change before I blog again! Definitely check out the Amazon stuff and let me know what you think. On a sidenote, some of our team was out in Seattle meeting with the Amazon crew. Amazingly nice and wickedly smart people with huge visions. Thanks again to all those guys. To circle back to Obama and the future, leveraging the cloud is also the right thing to do from a green standpoint. Amazon and salesforce already have the servers and the data centers. No need to build the infrastructure yourself and incur all the electricity costs along with everything associated.
All the best,
ac 

The “First 500 Certified” tombstone arrived…. - January 13, 2009 at 10:51 am

You can follow Reid Carlberg on Twitter.

 

 

…along with a pretty decent fleece.

This Force.com First 500 Certified thing — it’s like the gift that keeps on giving.  (First the pin & hat, the certificate and now this.  A bonanza!)

 

Bye-Bye CardScan? - January 9, 2009 at 10:32 am

In case you haven’t heard we announced CardLasso back in November of last year.  We have had a lot of interest and received some great feedback since it was shown in the Dreamforce keynote by Adam Gross, namely:

  • This is great, but I don’t have an iPhone
  • Could I use this for Tradeshows?
  • Do you have any Corporate plan options

I’m glad to say that we have now implemented each of the above suggestions and they are either live in Lasso, or are currently in beta.  

Card Entry via Web Cam
If you don’t have an iPhone you can enter cards directly from your laptop or PC with an attached USB Web Cam.  This option allows for high-volume card entry and doesn’t require a proprietary scanner (such as CardScan).  

Other Mobile Phones
We also have a new mobile offering that will allow you to enter cards from ANY mobile phone (including Blackberries which you have all asked about).  This approach will work with any phone that allows you to take a picture and send an email.

Native Blackberry Client
We are also developing a native Blackberry client to have even tighter integration with this platform, so if you are excited about the new Blackberry Storm you got for Christmas, stay tuned.

Lasso Offline for Tradeshows
If you are in marketing and go to tradeshows, you know the pain of entering hundreds or thousands of business cards.  We utilized our 2Go mobile platform and built a special offline version of Lasso that allows you to rapidly capture pictures of cards using a web cam in an offline mode and then they can be uploaded for transcription once you have Internet connectivity.

We are very excited about Lasso and it is a great showcase of what can be done with force.com Sites.

If you are interested head over to http://www.lasso2go.com to sign up for a $1.99 trial to give this a spin.
 

Hooray – “Dirt Bound” now insanely popular. - January 9, 2009 at 8:16 am

You can follow Reid Carlberg on Twitter.

My prior ground-breaking* work on "dirt computing" has proven it’s worth!  "Dirt bound" is now insanely popular.  Or, if not insanely popular, it has appeared in at least one blog post outside of mine.  

Although I should probably admit that even that blog post is about my blog post, so it may be they had no other choice.

Chalk this one up as mildly amusing. :-)

 

(* get it? ground-breaking?  I know: Awe. Some.)

????????????????????????????????????????? - January 8, 2009 at 6:07 pm

 Cloud Converter(???????????)??????????????????????????(??????????)?????? 

 
????????????Google Code??????????????????Java???????????????????? 
 
?    ????????????JDBC???????????????????(Lotus Notes, Oracle, MySQL, ??)? 
?    ???????? 
?    ?????????????????? 
?    ??????????????????????????????????????? 
?    ????????????? 
 
???????????????ReadMe.txt??????????????
 
??????????????????rcarlberg@modelmetrics.com

Cloud Converter: Automatically turn your dirt bound db tables to Force.com objects - January 4, 2009 at 6:38 pm

(???

I just posted Cloud Converter to Google code.  It’s a bunch of Java code that:

** connects to a dirt bound database you specify — anything with a JDBC connector should work (MySQL, Lotus Notes, Microsoft SQL, Oracle)
** inspects the meta data
** creates a matching object in Force.com
** modifies the default page layout to include all of the fields and creates a custom tab for it
** moves data from the dirt to the cloud

Pretty straightforward.  The "ReadMe.txt" gives more detail.  I’ll be putting together a screen flow shortly.  Questions?  Drop me an email: rcarlberg@modelmetrics.com.

Model Metrics has released this as open source with an MIT License

Enjoy!

1/7 Update: This is now on Salesforce.com’s Code Share.