SlideShare uma empresa Scribd logo
1 de 70
SQLitePersistentObjects



Wednesday, March 11, 2009
SQLite Without the SQL
                            Jeff LaMarche




Wednesday, March 11, 2009
Contacting Me
                   • jeff_lamarche@mac.com
                   • http://iphonedevelopment.blogspot.com
                   • Twitter: jeff_lamarche




Wednesday, March 11, 2009
About Me
                   • Writer
                    • Beginning iPhone Development (Apress)
                    • Several Articles for ADC & MacTech Mag
                    • Beginning Cocoa (Apress, in progress)
                    • Regular blog postings


Wednesday, March 11, 2009
More About Me
                   • Programmer
                    • Primarily contract work
                    • Using Cocoa since about 2000
                    • OO Programming since early 1990s
                    • Programming since 1980
                    • Full-time with Cocoa for only a year

Wednesday, March 11, 2009
Image Source: http://www.macgeek.org/museum/bhapple2plus/page02.html




Wednesday, March 11, 2009
Wednesday, March 11, 2009
Enough About Me
                                (yeah, seriously)




Wednesday, March 11, 2009
SQLPO
                                 SQLitePersistentObjects

               • Object-Relational Mapping (ORM) Tool
                      or for the more technically-minded:

                      code that takes data from your program and
                      sticks it into or pulls it out of a relational
                      database




Wednesday, March 11, 2009
In the Beginning...
                  • Early OO programs that needed to use data
                            from a database embedded SQL statements
                            in code
                       • Difficult to maintain
                       • Strings are a “black box” to the compiler


Wednesday, March 11, 2009
ORM History
                  • 1996 Enterprise Object Frameworks (EOF)
                   • Part of NeXT’s Cocoa-Based WebObjects
                   • Used visual tool to map data objects to
                            database table
                       • Once model created, you interacted with
                            database tables as if they were objects
                       • Didn’t even have to create specific classes
                            if you didn’t want to
Wednesday, March 11, 2009
ORM History
                  • Basic idea was borrowed by other platforms,
                            changed to work with other languages,
                            sometimes extended to be better
                       • Hibernate, Cayenne, ADO .net, Outlet,
                             Django, many others




Wednesday, March 11, 2009
ORM History
                  • One language evolved the concept
                   • Ruby on Rails’ ActiveRecord
                     • No longer needed mapping document
                     • Object structure dynamically created
                            based on table structure in database




Wednesday, March 11, 2009
ORM History
                  • Core Data
                   • Core Data on the Mac is EOF’s stepchild
                   • Core Data is NOT EOF, but shares some
                            DNA




Wednesday, March 11, 2009
ORM History
                            Apple has not ported Core Data to the
                            iPhone (yet).


                            That fact is what triggered the birth of
                            SQLitePersistentObjects




Wednesday, March 11, 2009
SQLPO
                                    SQLitePersistentObjects

               • You can always find the latest version here:
                      http://code.google.com/p/sqlitepersistentobjects/
               • Add the code from the /src directory to your
                      Xcode project
               • Make sure to link to the SQLite3 dynamic library
                      at /usr/lib/libsqlite3.dylib




Wednesday, March 11, 2009
SQLPO
                                       SQLitePersistentObjects

          •      We have a support mailing list:
                 http://groups.google.com/group/sqlitepersistentobjects-user


          • Licensed under the New BSD License
             • Free, open source.
             • No attribution required, non-viral, can be used in
                            commercial projects, no need to publish your code
                    • If you can’t use BSD licensed code for some reason,
                            contact me - we’re flexible on the license.
Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

               •      To create a persistent object, you simply subclass
                      an existing class.
                            #import <Foundation/Foundation.h>
                            #import quot;SQLitePersistentObject.hquot;

                            @interface Person : SQLitePersistentObject
                            {
                            	 NSString	    *firstName;
                            	 NSString	    *lastName;
                            	 NSDate	 	    *birthdate;
                            	 int	 	   	   numberOfChildren;
                            	 float	   	   contribution;
                            	 UIImage	 	   *photo;
                            }
                            @property (nonatomic, retain) NSString *firstName;
                            @property (nonatomic, retain) NSString *lastName;
                            @property (nonatomic, retain) NSDate *birthdate;
                            @property int numberOfChildren;
                            @property float contribution;
                            @property (nonatomic, retain) UIImage *photo;
                            @end


Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

               •      To create a persistent object, you simply subclass
                      an existing class.
                            #import <Foundation/Foundation.h>
                            #import quot;SQLitePersistentObject.hquot;

                            @interface Person : SQLitePersistentObject
                            {
                            	 NSString	    *firstName;
                            	 NSString	    *lastName;
                            	 NSDate	 	    *birthdate;
                            	 int	 	   	   numberOfChildren;
                            	 float	   	   contribution;
                            	 UIImage	 	   *photo;
                            }
                            @property (nonatomic, retain) NSString *firstName;
                            @property (nonatomic, retain) NSString *lastName;
                            @property (nonatomic, retain) NSDate *birthdate;
                            @property int numberOfChildren;
                            @property float contribution;
                            @property (nonatomic, retain) UIImage *photo;
                            @end


Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

               •      To create a persistent object, you simply subclass
                      an existing class.
                            #import quot;Person.hquot;

                            @implementation Person
                            @synthesize firstName;
                            @synthesize lastName;
                            @synthesize birthdate;
                            @synthesize numberOfChildren;
                            @synthesize contribution;
                            @synthesize photo;
                            - (void)dealloc
                            {
                            	 [firstName release];
                            	 [lastName release];
                            	 [birthdate release];
                            	 [photo release];
                            	 [super dealloc];
                            }
                            @end



Wednesday, March 11, 2009
The Basics
                                             SQLitePersistentObjects


               •      Once you’ve defined a persistent object, creating a
                      new object and saving it to the database couldn’t
                      be easier:

                            	   Person *newPerson = [[Person alloc] init];
                            	   newPerson.firstName = @quot;Marthaquot;;
                            	   newPerson.lastName = @quot;Washingtonquot;;
                            	   newPerson.birthdate = [NSDate date];
                            	   newPerson.numberOfChildren = 5;
                            	   newPerson.contribution = 27.32;
                            	   newPerson.photo = [UIImage imageNamed:@quot;MarthaWashington.pngquot;];
                            	   [newPerson save];
                            	   [newPerson release];




Wednesday, March 11, 2009
The Basics
                                             SQLitePersistentObjects


               •      Once you’ve defined a persistent object, creating a
                      new object and saving it to the database couldn’t
                      be easier:

                            	   Person *newPerson = [[Person alloc] init];
                            	   newPerson.firstName = @quot;Marthaquot;;
                            	   newPerson.lastName = @quot;Washingtonquot;;
                            	   newPerson.birthdate = [NSDate date];
                            	   newPerson.numberOfChildren = 5;
                            	   newPerson.contribution = 27.32;
                            	   newPerson.photo = [UIImage imageNamed:@quot;MarthaWashington.pngquot;];
                            	   [newPerson save];
                            	   [newPerson release];




Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects


               •      How does it save the data?

                            •   Raw datatypes are mapped to appropriate
                                columns

                                •   e.g. int goes into INTEGER field, float goes
                                    into REAL field

                            •   Other persistent objects are stored as
                                references to the row and table where that
                                object is stored


Wednesday, March 11, 2009
The Basics
                                          SQLitePersistentObjects


               •      How does it save the data? (cont)

                            •   Objects that aren’t subclasses of
                                SQLitePersistentObject get stored IF they
                                conform to a protocol called SQLitePersistence

                            •   We have provided categories for most common
                                objects to conform them to SQLitePersistence
                                •   NSString, NSNumber, UIImage, UIColor, NSData,
                                    NSDate, NSMutableData



Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects


               •      How does it save the data? (cont)

                            •   We also provide category on NSObject as a
                                fallback. Any object that doesn’t conform to
                                SQLitePersistence but that does conform to
                                NSCoding can be stored in the database, but
                                gets archived as a BLOB, which can’t be
                                searched or used in criteria-based queries.




Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects


               •      How does it save the data? (cont)

                            •   Dictionaries, Arrays, and Sets do not get stored
                                in a column in the object’s table, but rather get
                                stored in a child table.

                                •   Each item in collection gets one row in the
                                    child table

                                •   Raw Datatypes and non-persistent objects get
                                    stored right in child table

                                •   Persistent objects get stored as references
Wednesday, March 11, 2009
The Basics
                                        SQLitePersistentObjects


               •      How does it save the data? (cont)

                            •   Every objects gets assigned a primary key value,
                                which is an integer that acts as a unique
                                identifier for that object

                            •   Stored in a private instance variable called pk

                            •   Used in some cases load objects from database




Wednesday, March 11, 2009
The Basics
                                        SQLitePersistentObjects


               •      Loading an object from the database is
                      accomplished through class methods. This is the
                      simplest one:
                            	 Person *martha = [Person findByPK:1];




Wednesday, March 11, 2009
The Basics
                                        SQLitePersistentObjects


               •      You can load all objects into an array. Be careful
                      doing this, however, as it is not a very efficient use
                      of memory in most cases.
                            	 NSArray *people = [Person allObjects];




Wednesday, March 11, 2009
The Basics
                                        SQLitePersistentObjects


               •      SQLPO also creates dynamic find methods based
                      on your property names:


                            	 NSArray *people = [Person allObjects];




                            	 NSArray *people = [Person findByLastName:@quot;Washingtonquot;];




Wednesday, March 11, 2009
The Basics
                                        SQLitePersistentObjects


               •      Dynamic find by methods support SQL wildcards



                            	 NSArray *people = [Person allObjects];




                            	 NSArray *people = [Person findByLastName:@quot;Washingtonquot;];




                            	 NSArray *people = [Person findByLastName:@quot;Wash%quot;];




Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects
                            #import <Foundation/Foundation.h>
                            #import quot;SQLitePersistentObject.hquot;

                            @interface Person : SQLitePersistentObject
                            {
                            	 NSString	      *firstName;
                            	 NSString	      *lastName;
                            	 NSDate	    	   *birthdate;
                            	 int	 	     	   numberOfChildren;
                            	 float		        contribution;
                            	 UIImage	 	     *photo;
                            }
                            @property (nonatomic, retain) NSString *firstName;
                            @property (nonatomic, retain) NSString *lastName;
                            @property (nonatomic, retain) NSDate *birthdate;
                            @property int numberOfChildren;
                            @property float contribution;
                            @property (nonatomic, retain) UIImage *photo;
                            @end

                            @interface Person (squelch)
                            + (id)findByName:(NSString *)theName;
                            @end




Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects
                            #import <Foundation/Foundation.h>
                            #import quot;SQLitePersistentObject.hquot;

                            @interface Person : SQLitePersistentObject
                            {
                            	 NSString	      *firstName;
                            	 NSString	      *lastName;
                            	 NSDate	    	   *birthdate;
                            	 int	 	     	   numberOfChildren;
                            	 float		        contribution;
                            	 UIImage	 	     *photo;
                            }
                            @property (nonatomic, retain) NSString *firstName;
                            @property (nonatomic, retain) NSString *lastName;
                            @property (nonatomic, retain) NSDate *birthdate;
                            @property int numberOfChildren;
                            @property float contribution;
                            @property (nonatomic, retain) UIImage *photo;
                            @end

                            @interface Person (squelch)
                            + (id)findByName:(NSString *)theName;
                            @end




Wednesday, March 11, 2009
The Basics
                                           SQLitePersistentObjects


               •      If you need more flexibility, you can always specify
                      the exact criteria by supplying a SQL where clause
                      with findByCriteria:
                     	 NSArray *people = [Person findByCriteria:@quot;WHERE first_name = 'John' and last_name like
                     'S%' and date(birthdate) <= date('now')quot;];




Wednesday, March 11, 2009
The Basics
                                           SQLitePersistentObjects


               •      If you need more flexibility, you can always specify
                      the exact criteria by supplying a SQL where clause
                      with findByCriteria:
                     	 NSArray *people = [Person findByCriteria:@quot;WHERE first_name = 'John' and last_name like
                     'S%' and date(birthdate) <= date('now')quot;];




                                   Note: Property firstName
                                         becomes column first_name



Wednesday, March 11, 2009
The Basics
                                            SQLitePersistentObjects


               •      You can find out the column name for a property
                      name like so:



                            #import quot;NSString-SQLiteColumnName.hquot;
                            …
                            NSString *columnName = [@quot;firstNamequot; stringAsSQLColumnName];




Wednesday, March 11, 2009
The Basics
                                          SQLitePersistentObjects


               •      If you only want the first object that meets your
                      criteria, you can do that also:



                          Person *firstPerson = [Person findFirstByCriteria:@quot;WHERE first_name =
                      'John' and last_name like 'S%' and date(birthdate) <= date('now')quot;];




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects


               •      Deleting an object should be done using the class
                      method deleteObject:cascade:, which takes the
                      primary key of the object to be deleted.


                            [Person deleteObject:5 cascade:YES];




Wednesday, March 11, 2009
The Basics
                                            SQLitePersistentObjects


               •      Database tables can benefit from adding indices to
                      them. SQLitePersistentObjects has a mechanism
                      for adding indices without writing SQL. Override
                      this method in your class:

                            +(NSArray *)indices
                            {
                            	   return nil;
                            }




Wednesday, March 11, 2009
The Basics
                                            SQLitePersistentObjects


               •      Method should return an array of arrays. Each
                      contained array represents one index and should
                      have the properties to be indexed in the order
                      they should be in the index.

                            +(NSArray *)indices
                            {
                            	   NSArray *firstIndex = [NSArray arrayWithObjects:@quot;lastNamequot;,
                            @quot;firstNamequot;, @quot;pkquot;, nil];
                            	   NSArray *secondIndex = [NSArray arrayWithObjects:@quot;birthdatequot;, @quot;pkquot;,
                            nil];
                            	   return [NSArray arrayWithObjects:firstIndex, secondIndex, nil];
                            }




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

               •      Let’s look at our class declaration again.

                            #import <Foundation/Foundation.h>
                            #import quot;SQLitePersistentObject.hquot;

                            @interface Person : SQLitePersistentObject
                            {
                            	 NSString	    *firstName;
                            	 NSString	    *lastName;
                            	 NSDate	 	    *birthdate;
                            	 int	 	   	   numberOfChildren;
                            	 float	   	   contribution;
                            	 UIImage	 	   *photo;
                            }
                            @property (nonatomic, retain) NSString *firstName;
                            @property (nonatomic, retain) NSString *lastName;
                            @property (nonatomic, retain) NSDate *birthdate;
                            @property int numberOfChildren;
                            @property float contribution;
                            @property (nonatomic, retain) UIImage *photo;
                            @end


Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

               •      Let’s look at our class declaration again.

                            #import <Foundation/Foundation.h>
                            #import quot;SQLitePersistentObject.hquot;

                            @interface Person : SQLitePersistentObject
                            {
                            	 NSString	    *firstName;
                            	 NSString	    *lastName;
                            	 NSDate	 	    *birthdate;
                            	 int	 	   	   numberOfChildren;
                            	 float	   	   contribution;
                            	 UIImage	 	   *photo;
                            }
                            @property (nonatomic, retain) NSString *firstName;
                            @property (nonatomic, retain) NSString *lastName;
                            @property (nonatomic, retain) NSDate *birthdate;
                            @property int numberOfChildren;
                            @property float contribution;
                            @property (nonatomic, retain) UIImage *photo;
                            @end


Wednesday, March 11, 2009
The Basics
                                  SQLitePersistentObjects

               •      Let’s look at our class declaration again.




Wednesday, March 11, 2009
The Basics
                                          SQLitePersistentObjects

               •      Let’s talk about Paired Arrays.

                            •   Simple Concept - Multiple Arrays

                            •   Every array has same number of rows

                            •   Object at same index in each array
                                corresponds to information about the same
                                object

                                •   e.g. fifth object in one array might hold Joe’s
                                    age, and the fifth object in the other array
                                    might hold Joe’s last name.

Wednesday, March 11, 2009
The Basics
                                   SQLitePersistentObjects

               •      Let’s talk about Paired Arrays (cont)

               •      Can have as many arrays as necessary.

               •      SQLPO has built-in method to return specified
                      paired arrays.

               •      It packs all the paired arrays together inside
                      another array

               •      First array in the array always contains a list of the
                      primary keys.


Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             1               Martha            Washington
                             2                 Joe               Smith
                             3                Sally               Ride
                             4               George            Washington
                             5               Buster             Keaton




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             1               Martha            Washington
                             2                 Joe               Smith
                             3                Sally               Ride
                             4               George            Washington
                             5               Buster             Keaton




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             1               Martha            Washington
                             2                 Joe               Smith
                             3                Sally               Ride
                             4               George            Washington
                             5               Buster             Keaton




Wednesday, March 11, 2009
The Basics
                                  SQLitePersistentObjects

               •      This means we can load in only the information we
                      need to display in the table, along with the
                      information we need to load the full object if the
                      user selects it.




Wednesday, March 11, 2009
The Basics
                                      SQLitePersistentObjects

               •      In our controller class, we’ll need mutable arrays to
                      hold the data.
                            #import <UIKit/UIKit.h>

                            @interface PeopleListViewController : UITableViewController
                            {
                            	 NSMutableArray	 *pks;
                            	 NSMutableArray	 *firstNames;
                            	 NSMutableArray	 *lastNames;
                            }
                            @property (nonatomic, retain) NSMutableArray *pks;
                            @property (nonatomic, retain) NSMutableArray *firstNames;
                            @property (nonatomic, retain) NSMutableArray *lastNames;
                            - (void)refreshData;
                            @end




               •      We also declare a method for loading the arrays.

Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects

               •      Getting the paired arrays is simple enough:
                  - (void)refreshData
                  {
                  	 NSArray *array = [Person pairedArraysForProperties:[NSArray
                  arrayWithObjects:@quot;firstNamequot;, @quot;lastNamequot;, nil] withCriteria:@quot;where birthdate is not
                  nullquot;];
                  	 self.pks = [array objectAtIndex:0];
                  	 self.firstNames = [array objectAtIndex:1];
                  	 self.lastNames = [array objectAtIndex:2];
                  }



               •      Just tell it which properties you want, and it will
                      give you all those plus the primary keys.




Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects

               •      In our Table View Data Source, we just get a count
                      of one of the arrays so we know the number of
                      rows we need in our table:
                  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
                  (NSInteger)section
                  {
                      return [pks count];
                  }




Wednesday, March 11, 2009
The Basics
                                        SQLitePersistentObjects

                •     We can then use the information from the arrays
                      to populate our table:
            - (UITableViewCell *)tableView:(UITableView *)tableView
            		       cellForRowAtIndexPath:(NSIndexPath *)indexPath
            {
                static NSString *CellIdentifier = @quot;Cellquot;;

                  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
                  if (cell == nil)
            	     {
                      cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
            	   	     	   	   	    	   	   	   	      reuseIdentifier:CellIdentifier] autorelease];
                  }
            	     NSUInteger row = [indexPath row];
                  cell.text = [NSString stringWithFormat:@quot;%@, %@quot;,
            	   	     	   	     [lastNames objectAtIndex:row],
            	   	     	   	     [firstNames objectAtIndex:row]];

                  return cell;
            }




Wednesday, March 11, 2009
The Basics
                                         SQLitePersistentObjects

               •      When the user selects a row, we grab the primary
                      key for the selected row, and use that to load the
                      Person:

                  - (void)tableView:(UITableView *)tableView
                  didSelectRowAtIndexPath:(NSIndexPath *)indexPath
                  {
                  	 int	 thePk = [[pks objectAtIndex:[indexPath row]] intValue];
                  	 Person *thePerson = (Person *)[Person findByPK:thePk];
                  	 // Do something with the person here...
                  }




Wednesday, March 11, 2009
The Basics
                                SQLitePersistentObjects

                            Easy Enough, but there’s a problem.


                            What if you want to sort the arrays?




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             1               Martha            Washington
                             2                 Joe               Smith
                             3                Sally               Ride
                             4               George            Washington
                             5               Buster             Keaton




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             1               Buster             Keaton
                             2               George               Ride
                             3                 Joe               Smith
                             4               Martha            Washington
                             5                Sally            Washington




Wednesday, March 11, 2009
The Basics
                                            SQLitePersistentObjects

               • Categories to the Rescue!
               • Just call sortArrayUsingSelector:withPairedMutableArrays:
                            	   [lastNames sortArrayUsingSelector:@selector(compare:)
                            	   	    	     withPairedMutableArrays:firstNames, pks, nil];




               • Now all three arrays are sorted based on the last
                      name of the people represented in the arrays.




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             1               Martha            Washington
                             2                 Joe               Smith
                             3                Sally               Ride
                             4               George            Washington
                             5               Buster             Keaton




Wednesday, March 11, 2009
The Basics
                                     SQLitePersistentObjects

                                  Example: Three NSArrays
                            pks           firstNames            lastNames
                             5               Buster             Keaton
                             4               George            Washington
                             2                 Joe               Smith
                             1               Martha            Washington
                             3                Sally               Ride




Wednesday, March 11, 2009
The Not-So-Basics
                                             SQLitePersistentObjects

               • SQLite makes aggregations easy (if you know SQL)

                double averageAge = [Person performSQLAggregation:
                @quot;select avg(date('now') - date(birthdate)) from people where birthdate is not nullquot;];




Wednesday, March 11, 2009
The Not-So-Basics
                                              SQLitePersistentObjects

               • But, if you don’t know SQL… you’re not totally out
                      of luck. SQLPO creates dynamic methods for
                      common aggregations based on your objects’
                      properties:

    	   NSNumber     *average = [Person averageOfContribution];
    	   NSNumber     *washAverage = [Person averageOfContributionWithCriteria:@quot;where name = 'Washington'quot;];
    	   NSNumber     *sum = [Person sumOfContribution];
    	   NSNumber     *washSum = [Person sumOfContributionWithCriteria:@quot;where name = 'Washington'quot;];
    	   NSNumber     *count = [Person countOfPk];
    	   NSNumber     *min = [Person minOfContribution];
    	   NSNumber     *washMin = [Person minOfContributionWithCriteria:@quot;where name = 'Washington'quot;];
    	   NSNumber     *max = [Person maxOfContribution];
    	   NSNumber     *washMax = [Person maxOfContributionWithCriteria:@quot;where name = 'Washington'quot;];




Wednesday, March 11, 2009
The Not-So-Basics
                                          SQLitePersistentObjects

               • Defining how non-standard, non-persistent objects
                      get stored.

                      @protocol SQLitePersistence
                      @required
                      + (BOOL)canBeStoredInSQLite;
                      + (NSString *)columnTypeForObjectStorage;
                      + (BOOL)shouldBeStoredInBlob;
                      @optional
                      + (id)objectWithSqlColumnRepresentation:(NSString *)columnData;
                      - (NSData *)sqlBlobRepresentationOfSelf;
                      + (id)objectWithSQLBlobRepresentation:(NSData *)data;
                      - (NSString *)sqlColumnRepresentationOfSelf;
                      @end




Wednesday, March 11, 2009
The Not-So-Basics
                                     SQLitePersistentObjects

               • The Instance Manager
               • SQLPO has a singleton class that manages the
                      database instance.
               • Mostly, this class is used behind-the-scenes without
                      any need for you to interact with it.
               • But... it’s there if you need it.




Wednesday, March 11, 2009
The Not-So-Basics
                                              SQLitePersistentObjects

               • Getting the shared instance:
                     SQLiteInstanceManager *manager = [SQLiteInstanceManager sharedManager];




Wednesday, March 11, 2009
The Not-So-Basics
                                        SQLitePersistentObjects

               • Once you have it, what can you do with it?

               • Get a reference to the database
                                      sqlite3 *db = [manager database];



               • Execute arbitrary SQL Updates:
                             [manager executeUpdateSQL:@quot;update foo set bar = 1quot;];




Wednesday, March 11, 2009
The Not-So-Basics
                                        SQLitePersistentObjects

               • Once you have it, what can you do with it? (cont)

               • Find out if a table exists in the database.
                            	   BOOL exists = [manager tableExists:@quot;superheroesquot;];




               • Change database configuration and do maintenance
                            	   [manager vacuum];
                            	   [manager setCacheSize:100]




Wednesday, March 11, 2009
Performance
                                            SQLitePersistentObjects

               • What Lies Ahead
                            • validation architecture & willSave/didSave/okayToSave:
                            • transient properties
                            • performance optimizations
                            • rollback
                            • refactoring to generalize code where makes sense
                            • ??? (ideas welcome)



Wednesday, March 11, 2009
Performance
                               SQLitePersistentObjects

               • How well does it perform?
                  • Umm... good question.
                  • Can we get back to you on that?




Wednesday, March 11, 2009
SQLitePersistentObjects




                                 Questions?



Wednesday, March 11, 2009

Mais conteúdo relacionado

Semelhante a Sqlpo Presentation

Objective-C A Beginner's Dive (with notes)
Objective-C A Beginner's Dive (with notes)Objective-C A Beginner's Dive (with notes)
Objective-C A Beginner's Dive (with notes)Altece
 
Objective-C A Beginner's Dive
Objective-C A Beginner's DiveObjective-C A Beginner's Dive
Objective-C A Beginner's DiveAltece
 
I phone udvikling best brains
I phone udvikling best brainsI phone udvikling best brains
I phone udvikling best brainsOve larsen
 
Connecting to a REST API in iOS
Connecting to a REST API in iOSConnecting to a REST API in iOS
Connecting to a REST API in iOSgillygize
 
Developing Cocoa Applications with macRuby
Developing Cocoa Applications with macRubyDeveloping Cocoa Applications with macRuby
Developing Cocoa Applications with macRubyBrendan Lim
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeRebecca Murphey
 
Introduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim SummitIntroduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim SummitRan Mizrahi
 
Entity Framework V1 and V2
Entity Framework V1 and V2Entity Framework V1 and V2
Entity Framework V1 and V2ukdpe
 
Extending Spring for Custom Usage
Extending Spring for Custom UsageExtending Spring for Custom Usage
Extending Spring for Custom UsageJoshua Long
 
Plone in the Cloud - an on-demand CMS hosted on Amazon EC2
Plone in the Cloud - an on-demand CMS hosted on Amazon EC2Plone in the Cloud - an on-demand CMS hosted on Amazon EC2
Plone in the Cloud - an on-demand CMS hosted on Amazon EC2Jazkarta, Inc.
 
Introduction to MVC in iPhone Development
Introduction to MVC in iPhone DevelopmentIntroduction to MVC in iPhone Development
Introduction to MVC in iPhone DevelopmentVu Tran Lam
 
MacRuby - When objective-c and Ruby meet
MacRuby - When objective-c and Ruby meetMacRuby - When objective-c and Ruby meet
MacRuby - When objective-c and Ruby meetMatt Aimonetti
 
Core data intermediate Workshop at NSSpain 2013
Core data intermediate Workshop at NSSpain 2013Core data intermediate Workshop at NSSpain 2013
Core data intermediate Workshop at NSSpain 2013Diego Freniche Brito
 
Lecture 10 slides (february 4, 2010)
Lecture 10 slides (february 4, 2010)Lecture 10 slides (february 4, 2010)
Lecture 10 slides (february 4, 2010)Bruce Lee
 
2011 codestrong-abstracting-databases-access-in-titanium-mobile
2011 codestrong-abstracting-databases-access-in-titanium-mobile2011 codestrong-abstracting-databases-access-in-titanium-mobile
2011 codestrong-abstracting-databases-access-in-titanium-mobileAxway Appcelerator
 
Abstracting databases access in Titanium Mobile
Abstracting databases access in Titanium MobileAbstracting databases access in Titanium Mobile
Abstracting databases access in Titanium MobileXavier Lacot
 

Semelhante a Sqlpo Presentation (20)

Objective-C A Beginner's Dive (with notes)
Objective-C A Beginner's Dive (with notes)Objective-C A Beginner's Dive (with notes)
Objective-C A Beginner's Dive (with notes)
 
Objective-C A Beginner's Dive
Objective-C A Beginner's DiveObjective-C A Beginner's Dive
Objective-C A Beginner's Dive
 
I phone udvikling best brains
I phone udvikling best brainsI phone udvikling best brains
I phone udvikling best brains
 
Advanced Action Script
Advanced Action ScriptAdvanced Action Script
Advanced Action Script
 
Connecting to a REST API in iOS
Connecting to a REST API in iOSConnecting to a REST API in iOS
Connecting to a REST API in iOS
 
Developing Cocoa Applications with macRuby
Developing Cocoa Applications with macRubyDeveloping Cocoa Applications with macRuby
Developing Cocoa Applications with macRuby
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
Introduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim SummitIntroduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim Summit
 
Entity Framework V1 and V2
Entity Framework V1 and V2Entity Framework V1 and V2
Entity Framework V1 and V2
 
Extending Spring for Custom Usage
Extending Spring for Custom UsageExtending Spring for Custom Usage
Extending Spring for Custom Usage
 
Plone in the Cloud - an on-demand CMS hosted on Amazon EC2
Plone in the Cloud - an on-demand CMS hosted on Amazon EC2Plone in the Cloud - an on-demand CMS hosted on Amazon EC2
Plone in the Cloud - an on-demand CMS hosted on Amazon EC2
 
Introduction to MVC in iPhone Development
Introduction to MVC in iPhone DevelopmentIntroduction to MVC in iPhone Development
Introduction to MVC in iPhone Development
 
MacRuby - When objective-c and Ruby meet
MacRuby - When objective-c and Ruby meetMacRuby - When objective-c and Ruby meet
MacRuby - When objective-c and Ruby meet
 
Memory Deduction Games
Memory Deduction GamesMemory Deduction Games
Memory Deduction Games
 
Core data intermediate Workshop at NSSpain 2013
Core data intermediate Workshop at NSSpain 2013Core data intermediate Workshop at NSSpain 2013
Core data intermediate Workshop at NSSpain 2013
 
Lecture 10 slides (february 4, 2010)
Lecture 10 slides (february 4, 2010)Lecture 10 slides (february 4, 2010)
Lecture 10 slides (february 4, 2010)
 
2011 codestrong-abstracting-databases-access-in-titanium-mobile
2011 codestrong-abstracting-databases-access-in-titanium-mobile2011 codestrong-abstracting-databases-access-in-titanium-mobile
2011 codestrong-abstracting-databases-access-in-titanium-mobile
 
Abstracting databases access in Titanium Mobile
Abstracting databases access in Titanium MobileAbstracting databases access in Titanium Mobile
Abstracting databases access in Titanium Mobile
 
Splash
SplashSplash
Splash
 
Chapter1
Chapter1Chapter1
Chapter1
 

Último

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 

Último (20)

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 

Sqlpo Presentation

  • 2. SQLite Without the SQL Jeff LaMarche Wednesday, March 11, 2009
  • 3. Contacting Me • jeff_lamarche@mac.com • http://iphonedevelopment.blogspot.com • Twitter: jeff_lamarche Wednesday, March 11, 2009
  • 4. About Me • Writer • Beginning iPhone Development (Apress) • Several Articles for ADC & MacTech Mag • Beginning Cocoa (Apress, in progress) • Regular blog postings Wednesday, March 11, 2009
  • 5. More About Me • Programmer • Primarily contract work • Using Cocoa since about 2000 • OO Programming since early 1990s • Programming since 1980 • Full-time with Cocoa for only a year Wednesday, March 11, 2009
  • 8. Enough About Me (yeah, seriously) Wednesday, March 11, 2009
  • 9. SQLPO SQLitePersistentObjects • Object-Relational Mapping (ORM) Tool or for the more technically-minded: code that takes data from your program and sticks it into or pulls it out of a relational database Wednesday, March 11, 2009
  • 10. In the Beginning... • Early OO programs that needed to use data from a database embedded SQL statements in code • Difficult to maintain • Strings are a “black box” to the compiler Wednesday, March 11, 2009
  • 11. ORM History • 1996 Enterprise Object Frameworks (EOF) • Part of NeXT’s Cocoa-Based WebObjects • Used visual tool to map data objects to database table • Once model created, you interacted with database tables as if they were objects • Didn’t even have to create specific classes if you didn’t want to Wednesday, March 11, 2009
  • 12. ORM History • Basic idea was borrowed by other platforms, changed to work with other languages, sometimes extended to be better • Hibernate, Cayenne, ADO .net, Outlet, Django, many others Wednesday, March 11, 2009
  • 13. ORM History • One language evolved the concept • Ruby on Rails’ ActiveRecord • No longer needed mapping document • Object structure dynamically created based on table structure in database Wednesday, March 11, 2009
  • 14. ORM History • Core Data • Core Data on the Mac is EOF’s stepchild • Core Data is NOT EOF, but shares some DNA Wednesday, March 11, 2009
  • 15. ORM History Apple has not ported Core Data to the iPhone (yet). That fact is what triggered the birth of SQLitePersistentObjects Wednesday, March 11, 2009
  • 16. SQLPO SQLitePersistentObjects • You can always find the latest version here: http://code.google.com/p/sqlitepersistentobjects/ • Add the code from the /src directory to your Xcode project • Make sure to link to the SQLite3 dynamic library at /usr/lib/libsqlite3.dylib Wednesday, March 11, 2009
  • 17. SQLPO SQLitePersistentObjects • We have a support mailing list: http://groups.google.com/group/sqlitepersistentobjects-user • Licensed under the New BSD License • Free, open source. • No attribution required, non-viral, can be used in commercial projects, no need to publish your code • If you can’t use BSD licensed code for some reason, contact me - we’re flexible on the license. Wednesday, March 11, 2009
  • 18. The Basics SQLitePersistentObjects • To create a persistent object, you simply subclass an existing class. #import <Foundation/Foundation.h> #import quot;SQLitePersistentObject.hquot; @interface Person : SQLitePersistentObject { NSString *firstName; NSString *lastName; NSDate *birthdate; int numberOfChildren; float contribution; UIImage *photo; } @property (nonatomic, retain) NSString *firstName; @property (nonatomic, retain) NSString *lastName; @property (nonatomic, retain) NSDate *birthdate; @property int numberOfChildren; @property float contribution; @property (nonatomic, retain) UIImage *photo; @end Wednesday, March 11, 2009
  • 19. The Basics SQLitePersistentObjects • To create a persistent object, you simply subclass an existing class. #import <Foundation/Foundation.h> #import quot;SQLitePersistentObject.hquot; @interface Person : SQLitePersistentObject { NSString *firstName; NSString *lastName; NSDate *birthdate; int numberOfChildren; float contribution; UIImage *photo; } @property (nonatomic, retain) NSString *firstName; @property (nonatomic, retain) NSString *lastName; @property (nonatomic, retain) NSDate *birthdate; @property int numberOfChildren; @property float contribution; @property (nonatomic, retain) UIImage *photo; @end Wednesday, March 11, 2009
  • 20. The Basics SQLitePersistentObjects • To create a persistent object, you simply subclass an existing class. #import quot;Person.hquot; @implementation Person @synthesize firstName; @synthesize lastName; @synthesize birthdate; @synthesize numberOfChildren; @synthesize contribution; @synthesize photo; - (void)dealloc { [firstName release]; [lastName release]; [birthdate release]; [photo release]; [super dealloc]; } @end Wednesday, March 11, 2009
  • 21. The Basics SQLitePersistentObjects • Once you’ve defined a persistent object, creating a new object and saving it to the database couldn’t be easier: Person *newPerson = [[Person alloc] init]; newPerson.firstName = @quot;Marthaquot;; newPerson.lastName = @quot;Washingtonquot;; newPerson.birthdate = [NSDate date]; newPerson.numberOfChildren = 5; newPerson.contribution = 27.32; newPerson.photo = [UIImage imageNamed:@quot;MarthaWashington.pngquot;]; [newPerson save]; [newPerson release]; Wednesday, March 11, 2009
  • 22. The Basics SQLitePersistentObjects • Once you’ve defined a persistent object, creating a new object and saving it to the database couldn’t be easier: Person *newPerson = [[Person alloc] init]; newPerson.firstName = @quot;Marthaquot;; newPerson.lastName = @quot;Washingtonquot;; newPerson.birthdate = [NSDate date]; newPerson.numberOfChildren = 5; newPerson.contribution = 27.32; newPerson.photo = [UIImage imageNamed:@quot;MarthaWashington.pngquot;]; [newPerson save]; [newPerson release]; Wednesday, March 11, 2009
  • 23. The Basics SQLitePersistentObjects • How does it save the data? • Raw datatypes are mapped to appropriate columns • e.g. int goes into INTEGER field, float goes into REAL field • Other persistent objects are stored as references to the row and table where that object is stored Wednesday, March 11, 2009
  • 24. The Basics SQLitePersistentObjects • How does it save the data? (cont) • Objects that aren’t subclasses of SQLitePersistentObject get stored IF they conform to a protocol called SQLitePersistence • We have provided categories for most common objects to conform them to SQLitePersistence • NSString, NSNumber, UIImage, UIColor, NSData, NSDate, NSMutableData Wednesday, March 11, 2009
  • 25. The Basics SQLitePersistentObjects • How does it save the data? (cont) • We also provide category on NSObject as a fallback. Any object that doesn’t conform to SQLitePersistence but that does conform to NSCoding can be stored in the database, but gets archived as a BLOB, which can’t be searched or used in criteria-based queries. Wednesday, March 11, 2009
  • 26. The Basics SQLitePersistentObjects • How does it save the data? (cont) • Dictionaries, Arrays, and Sets do not get stored in a column in the object’s table, but rather get stored in a child table. • Each item in collection gets one row in the child table • Raw Datatypes and non-persistent objects get stored right in child table • Persistent objects get stored as references Wednesday, March 11, 2009
  • 27. The Basics SQLitePersistentObjects • How does it save the data? (cont) • Every objects gets assigned a primary key value, which is an integer that acts as a unique identifier for that object • Stored in a private instance variable called pk • Used in some cases load objects from database Wednesday, March 11, 2009
  • 28. The Basics SQLitePersistentObjects • Loading an object from the database is accomplished through class methods. This is the simplest one: Person *martha = [Person findByPK:1]; Wednesday, March 11, 2009
  • 29. The Basics SQLitePersistentObjects • You can load all objects into an array. Be careful doing this, however, as it is not a very efficient use of memory in most cases. NSArray *people = [Person allObjects]; Wednesday, March 11, 2009
  • 30. The Basics SQLitePersistentObjects • SQLPO also creates dynamic find methods based on your property names: NSArray *people = [Person allObjects]; NSArray *people = [Person findByLastName:@quot;Washingtonquot;]; Wednesday, March 11, 2009
  • 31. The Basics SQLitePersistentObjects • Dynamic find by methods support SQL wildcards NSArray *people = [Person allObjects]; NSArray *people = [Person findByLastName:@quot;Washingtonquot;]; NSArray *people = [Person findByLastName:@quot;Wash%quot;]; Wednesday, March 11, 2009
  • 32. The Basics SQLitePersistentObjects #import <Foundation/Foundation.h> #import quot;SQLitePersistentObject.hquot; @interface Person : SQLitePersistentObject { NSString *firstName; NSString *lastName; NSDate *birthdate; int numberOfChildren; float contribution; UIImage *photo; } @property (nonatomic, retain) NSString *firstName; @property (nonatomic, retain) NSString *lastName; @property (nonatomic, retain) NSDate *birthdate; @property int numberOfChildren; @property float contribution; @property (nonatomic, retain) UIImage *photo; @end @interface Person (squelch) + (id)findByName:(NSString *)theName; @end Wednesday, March 11, 2009
  • 33. The Basics SQLitePersistentObjects #import <Foundation/Foundation.h> #import quot;SQLitePersistentObject.hquot; @interface Person : SQLitePersistentObject { NSString *firstName; NSString *lastName; NSDate *birthdate; int numberOfChildren; float contribution; UIImage *photo; } @property (nonatomic, retain) NSString *firstName; @property (nonatomic, retain) NSString *lastName; @property (nonatomic, retain) NSDate *birthdate; @property int numberOfChildren; @property float contribution; @property (nonatomic, retain) UIImage *photo; @end @interface Person (squelch) + (id)findByName:(NSString *)theName; @end Wednesday, March 11, 2009
  • 34. The Basics SQLitePersistentObjects • If you need more flexibility, you can always specify the exact criteria by supplying a SQL where clause with findByCriteria: NSArray *people = [Person findByCriteria:@quot;WHERE first_name = 'John' and last_name like 'S%' and date(birthdate) <= date('now')quot;]; Wednesday, March 11, 2009
  • 35. The Basics SQLitePersistentObjects • If you need more flexibility, you can always specify the exact criteria by supplying a SQL where clause with findByCriteria: NSArray *people = [Person findByCriteria:@quot;WHERE first_name = 'John' and last_name like 'S%' and date(birthdate) <= date('now')quot;]; Note: Property firstName becomes column first_name Wednesday, March 11, 2009
  • 36. The Basics SQLitePersistentObjects • You can find out the column name for a property name like so: #import quot;NSString-SQLiteColumnName.hquot; … NSString *columnName = [@quot;firstNamequot; stringAsSQLColumnName]; Wednesday, March 11, 2009
  • 37. The Basics SQLitePersistentObjects • If you only want the first object that meets your criteria, you can do that also: Person *firstPerson = [Person findFirstByCriteria:@quot;WHERE first_name = 'John' and last_name like 'S%' and date(birthdate) <= date('now')quot;]; Wednesday, March 11, 2009
  • 38. The Basics SQLitePersistentObjects • Deleting an object should be done using the class method deleteObject:cascade:, which takes the primary key of the object to be deleted. [Person deleteObject:5 cascade:YES]; Wednesday, March 11, 2009
  • 39. The Basics SQLitePersistentObjects • Database tables can benefit from adding indices to them. SQLitePersistentObjects has a mechanism for adding indices without writing SQL. Override this method in your class: +(NSArray *)indices { return nil; } Wednesday, March 11, 2009
  • 40. The Basics SQLitePersistentObjects • Method should return an array of arrays. Each contained array represents one index and should have the properties to be indexed in the order they should be in the index. +(NSArray *)indices { NSArray *firstIndex = [NSArray arrayWithObjects:@quot;lastNamequot;, @quot;firstNamequot;, @quot;pkquot;, nil]; NSArray *secondIndex = [NSArray arrayWithObjects:@quot;birthdatequot;, @quot;pkquot;, nil]; return [NSArray arrayWithObjects:firstIndex, secondIndex, nil]; } Wednesday, March 11, 2009
  • 41. The Basics SQLitePersistentObjects • Let’s look at our class declaration again. #import <Foundation/Foundation.h> #import quot;SQLitePersistentObject.hquot; @interface Person : SQLitePersistentObject { NSString *firstName; NSString *lastName; NSDate *birthdate; int numberOfChildren; float contribution; UIImage *photo; } @property (nonatomic, retain) NSString *firstName; @property (nonatomic, retain) NSString *lastName; @property (nonatomic, retain) NSDate *birthdate; @property int numberOfChildren; @property float contribution; @property (nonatomic, retain) UIImage *photo; @end Wednesday, March 11, 2009
  • 42. The Basics SQLitePersistentObjects • Let’s look at our class declaration again. #import <Foundation/Foundation.h> #import quot;SQLitePersistentObject.hquot; @interface Person : SQLitePersistentObject { NSString *firstName; NSString *lastName; NSDate *birthdate; int numberOfChildren; float contribution; UIImage *photo; } @property (nonatomic, retain) NSString *firstName; @property (nonatomic, retain) NSString *lastName; @property (nonatomic, retain) NSDate *birthdate; @property int numberOfChildren; @property float contribution; @property (nonatomic, retain) UIImage *photo; @end Wednesday, March 11, 2009
  • 43. The Basics SQLitePersistentObjects • Let’s look at our class declaration again. Wednesday, March 11, 2009
  • 44. The Basics SQLitePersistentObjects • Let’s talk about Paired Arrays. • Simple Concept - Multiple Arrays • Every array has same number of rows • Object at same index in each array corresponds to information about the same object • e.g. fifth object in one array might hold Joe’s age, and the fifth object in the other array might hold Joe’s last name. Wednesday, March 11, 2009
  • 45. The Basics SQLitePersistentObjects • Let’s talk about Paired Arrays (cont) • Can have as many arrays as necessary. • SQLPO has built-in method to return specified paired arrays. • It packs all the paired arrays together inside another array • First array in the array always contains a list of the primary keys. Wednesday, March 11, 2009
  • 46. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 1 Martha Washington 2 Joe Smith 3 Sally Ride 4 George Washington 5 Buster Keaton Wednesday, March 11, 2009
  • 47. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 1 Martha Washington 2 Joe Smith 3 Sally Ride 4 George Washington 5 Buster Keaton Wednesday, March 11, 2009
  • 48. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 1 Martha Washington 2 Joe Smith 3 Sally Ride 4 George Washington 5 Buster Keaton Wednesday, March 11, 2009
  • 49. The Basics SQLitePersistentObjects • This means we can load in only the information we need to display in the table, along with the information we need to load the full object if the user selects it. Wednesday, March 11, 2009
  • 50. The Basics SQLitePersistentObjects • In our controller class, we’ll need mutable arrays to hold the data. #import <UIKit/UIKit.h> @interface PeopleListViewController : UITableViewController { NSMutableArray *pks; NSMutableArray *firstNames; NSMutableArray *lastNames; } @property (nonatomic, retain) NSMutableArray *pks; @property (nonatomic, retain) NSMutableArray *firstNames; @property (nonatomic, retain) NSMutableArray *lastNames; - (void)refreshData; @end • We also declare a method for loading the arrays. Wednesday, March 11, 2009
  • 51. The Basics SQLitePersistentObjects • Getting the paired arrays is simple enough: - (void)refreshData { NSArray *array = [Person pairedArraysForProperties:[NSArray arrayWithObjects:@quot;firstNamequot;, @quot;lastNamequot;, nil] withCriteria:@quot;where birthdate is not nullquot;]; self.pks = [array objectAtIndex:0]; self.firstNames = [array objectAtIndex:1]; self.lastNames = [array objectAtIndex:2]; } • Just tell it which properties you want, and it will give you all those plus the primary keys. Wednesday, March 11, 2009
  • 52. The Basics SQLitePersistentObjects • In our Table View Data Source, we just get a count of one of the arrays so we know the number of rows we need in our table: - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section { return [pks count]; } Wednesday, March 11, 2009
  • 53. The Basics SQLitePersistentObjects • We can then use the information from the arrays to populate our table: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @quot;Cellquot;; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; } NSUInteger row = [indexPath row]; cell.text = [NSString stringWithFormat:@quot;%@, %@quot;, [lastNames objectAtIndex:row], [firstNames objectAtIndex:row]]; return cell; } Wednesday, March 11, 2009
  • 54. The Basics SQLitePersistentObjects • When the user selects a row, we grab the primary key for the selected row, and use that to load the Person: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { int thePk = [[pks objectAtIndex:[indexPath row]] intValue]; Person *thePerson = (Person *)[Person findByPK:thePk]; // Do something with the person here... } Wednesday, March 11, 2009
  • 55. The Basics SQLitePersistentObjects Easy Enough, but there’s a problem. What if you want to sort the arrays? Wednesday, March 11, 2009
  • 56. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 1 Martha Washington 2 Joe Smith 3 Sally Ride 4 George Washington 5 Buster Keaton Wednesday, March 11, 2009
  • 57. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 1 Buster Keaton 2 George Ride 3 Joe Smith 4 Martha Washington 5 Sally Washington Wednesday, March 11, 2009
  • 58. The Basics SQLitePersistentObjects • Categories to the Rescue! • Just call sortArrayUsingSelector:withPairedMutableArrays: [lastNames sortArrayUsingSelector:@selector(compare:) withPairedMutableArrays:firstNames, pks, nil]; • Now all three arrays are sorted based on the last name of the people represented in the arrays. Wednesday, March 11, 2009
  • 59. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 1 Martha Washington 2 Joe Smith 3 Sally Ride 4 George Washington 5 Buster Keaton Wednesday, March 11, 2009
  • 60. The Basics SQLitePersistentObjects Example: Three NSArrays pks firstNames lastNames 5 Buster Keaton 4 George Washington 2 Joe Smith 1 Martha Washington 3 Sally Ride Wednesday, March 11, 2009
  • 61. The Not-So-Basics SQLitePersistentObjects • SQLite makes aggregations easy (if you know SQL) double averageAge = [Person performSQLAggregation: @quot;select avg(date('now') - date(birthdate)) from people where birthdate is not nullquot;]; Wednesday, March 11, 2009
  • 62. The Not-So-Basics SQLitePersistentObjects • But, if you don’t know SQL… you’re not totally out of luck. SQLPO creates dynamic methods for common aggregations based on your objects’ properties: NSNumber *average = [Person averageOfContribution]; NSNumber *washAverage = [Person averageOfContributionWithCriteria:@quot;where name = 'Washington'quot;]; NSNumber *sum = [Person sumOfContribution]; NSNumber *washSum = [Person sumOfContributionWithCriteria:@quot;where name = 'Washington'quot;]; NSNumber *count = [Person countOfPk]; NSNumber *min = [Person minOfContribution]; NSNumber *washMin = [Person minOfContributionWithCriteria:@quot;where name = 'Washington'quot;]; NSNumber *max = [Person maxOfContribution]; NSNumber *washMax = [Person maxOfContributionWithCriteria:@quot;where name = 'Washington'quot;]; Wednesday, March 11, 2009
  • 63. The Not-So-Basics SQLitePersistentObjects • Defining how non-standard, non-persistent objects get stored. @protocol SQLitePersistence @required + (BOOL)canBeStoredInSQLite; + (NSString *)columnTypeForObjectStorage; + (BOOL)shouldBeStoredInBlob; @optional + (id)objectWithSqlColumnRepresentation:(NSString *)columnData; - (NSData *)sqlBlobRepresentationOfSelf; + (id)objectWithSQLBlobRepresentation:(NSData *)data; - (NSString *)sqlColumnRepresentationOfSelf; @end Wednesday, March 11, 2009
  • 64. The Not-So-Basics SQLitePersistentObjects • The Instance Manager • SQLPO has a singleton class that manages the database instance. • Mostly, this class is used behind-the-scenes without any need for you to interact with it. • But... it’s there if you need it. Wednesday, March 11, 2009
  • 65. The Not-So-Basics SQLitePersistentObjects • Getting the shared instance: SQLiteInstanceManager *manager = [SQLiteInstanceManager sharedManager]; Wednesday, March 11, 2009
  • 66. The Not-So-Basics SQLitePersistentObjects • Once you have it, what can you do with it? • Get a reference to the database sqlite3 *db = [manager database]; • Execute arbitrary SQL Updates: [manager executeUpdateSQL:@quot;update foo set bar = 1quot;]; Wednesday, March 11, 2009
  • 67. The Not-So-Basics SQLitePersistentObjects • Once you have it, what can you do with it? (cont) • Find out if a table exists in the database. BOOL exists = [manager tableExists:@quot;superheroesquot;]; • Change database configuration and do maintenance [manager vacuum]; [manager setCacheSize:100] Wednesday, March 11, 2009
  • 68. Performance SQLitePersistentObjects • What Lies Ahead • validation architecture & willSave/didSave/okayToSave: • transient properties • performance optimizations • rollback • refactoring to generalize code where makes sense • ??? (ideas welcome) Wednesday, March 11, 2009
  • 69. Performance SQLitePersistentObjects • How well does it perform? • Umm... good question. • Can we get back to you on that? Wednesday, March 11, 2009
  • 70. SQLitePersistentObjects Questions? Wednesday, March 11, 2009

Notas do Editor

  1. And that is spelled with an &#x201C;A&#x201D; contrary to the sign out front.
  2. A lot of people guard their personal e-mail for fear of spam and other unwelcome e-mail in their inbox. I&#x2019;ve never been that smart. I&#x2019;m somewhat virtually promiscuous. I&#x2019;ve been using this e-mail address since Apple first started that service. I have had, and still have others, but this is the best way to reach me. I do try to respond to every e-mail I get, though sometimes I do get a little overwhelmed. If you send me an e-mail, and you don&#x2019;t get a response in a week, feel free to send another one. The only e-mails I ignore on purpose are spam. The link is to my blog, focused on iPhone development from a technical standpoint, primarily. I post code, tutorials, etc., and also link to other good resources.
  3. If you know my name, it&#x2019;s probably from my writing. I do a fair amount of technical writing and there&#x2019;s no better way to cement your understanding of a technology then to try and explain it to somebody else. It&#x2019;s also a great way to raise your visibility in the community. Writing is what allowed me to go full-time with Cocoa / Apple technologies.
  4. Writing is great, but the bulk of my income comes from doing contract programming work. Prior to last March, I was doing mostly Enterprise Software consulting - travel-based programming for large corporate and government entities. Not exciting, but pays the bills, and because I used to be a developer for PeopleSoft, it was the easiest type of work for me to get. The release of the iPhone SDK and the book deal gave me the opportunity to finally jump with both feet into the Mac programming world.
  5. This slide is just for grins & giggles. This bad-boy (well, not this particular bad-boy, but one that looked like this) was what I used to write my first line of code... in Applesoft Basic. I include this because a lot of people don&#x2019;t believe me when I tell them I started coding on an Apple ][ made by Bell & Howell.
  6. We&#x2019;ve come a little way, haven&#x2019;t we?
  7. Fancy way of saying that it takes data stored in objects and stores and retrieves that data in and out of a relational database. Relational databases and OO programs use different, but comparable, paradigms.
  8. The SQL strings were &#x201C;black boxes&#x201D; as far as the compiler was concerned - you could put the Gettysburg Address into a string literal, and your program would happily pass that onto the SQL server.
  9. All software development builds on earlier stuff, so there may be earlier examples that could be thought of as forms of ORM, but many people recognize EOF as the first fully-fledged ORM tool, and it was the first one I used. WebObjects, though it&#x2019;s now Java-based, back in 1996 was Objective-C based, and it cost $50,000 a license. They were able to get that because the development time with WO & EOF was so much faster than the tools commonly in use at the time - primarily manual CGI coding. The basic idea behind EOF was that instead of writing SQL, you used a GUI tool to create mappings to a remote database. The mappings specified which objects and attributes corresponded to which tables and field. Once you created this mapping document (called an EOModel), you then interacted with the data in the database as if they were objects. This represented a HUGE step forward.
  10. WebObjects and EOF slowly fell to the side (yes, it still exists, but are not still widely used outside of Apple), while other development platforms took the ideas EOF pioneered, contorted them to fit the design patterns of other languages and, in some cases, extended them
  11. ActiveRecord is, in a sense, the logical extension of EOF. Ruby shares a lot of similarities with Objective-C, including a very dynamic nature - both languages allow methods and attributes to be added at runtime. ActiveRecord got rid of the need for an intermediate modeling tool, and leveraged the dynamic nature of the language to automatically create the class attributes based on the database table structure. When I first became aware of ActiveRecord, it was like the clouds parted and the angels sang. Seriously. If you&#x2019;ve ever done integration work, you know just how cool this idea is. One of the first times I experimented with ActiveRecord, I took a 270 line Java integration program and turned it into a 27 line Ruby script thanks to ActiveRecord and Ruby&#x2019;s terse syntax. Now, we&#x2019;re at a point where we have no SQL and no modeling tool. Your objects just take shape based on the contents of the database.
  12. With the release of Tiger, Apple gave us Core Data, which is not EOF, but is very heavily influenced by it, and almost certainly shares some code. Using Core Data is very similar to using EOF, except there&#x2019;s no remote database. They took the basic idea and reworked toward the needs of the workstation (laptop/desktop) application developer You design your data model visually, in a tool much like the one used to create the mappings in EOF, and by doing so (assuming you&#x2019;ve selected SQLite as your storage option), it automatically creates the underlying tables in an embedded SQLite database. It&#x2019;s great. But...
  13. When we were writing the early chapters of the iPhone SDK, things were changing all the time, and it was hard to get a straight answer about what things we were used to having in Cocoa would be available on the iPhone. At first, Interface Builder wasn&#x2019;t there, but by Beta4, we had a mostly functioning IB. At some point, it became clear that Core Data wasn&#x2019;t going to be ported to the iPhone, at least for the initial release, even though SQLite was included on the iPhone. The iPhone documentation was recommending the use of SQLite for applications that had a lot of structured data, and Apple even posted sample code showing the &#x201C;recommended way&#x201D; to access SQLite in your applications - the old fashioned way, embedding static SQL strings in your application. They basically wanted us to step back in time fifteen years and do it the way we did it before EOF existed. Well, no thank you.
  14. Here is a fully functional class declaration. Notice that we have properties that are objects, and native datatypes. That&#x2019;s all no problem. It can handle most raw datatypes, and most objects. It can&#x2019;t handle non-object pointers, like void * and char *, so you should use NSString instead of C-strings, and any chunk of memory that you have in a pointer, should be put into an NSData or NSMutableData. When it comes to objects, they are saved based on whether the implement a formal protocol. We have provided categories for most standard objects that tells SQLPO how to save those objects into the database, translate from the object to a table column, so the data is searchable. A property that is also a subclass of SQLitePersistentObjects will get stored in its own table, with a reference to that object&#x2019;s row and table being stored in this object. If there is no category (and the object is not also a subclass of SQLitePersistentObject, then it will look to see if the object conforms to NSCoding. If it does, it will archive the object into a blob. You must define properties for anything you want persisted into SQLite. Any non-persistent variables should not have properties. That&#x2019;s how SQLPO knows what to save and what not to save. Instance Variables without properties will not get saved to the database, nor will read-only properties.
  15. Here is a fully functional class declaration. Notice that we have properties that are objects, and native datatypes. That&#x2019;s all no problem. It can handle most raw datatypes, and most objects. It can&#x2019;t handle non-object pointers, like void * and char *, so you should use NSString instead of C-strings, and any chunk of memory that you have in a pointer, should be put into an NSData or NSMutableData. When it comes to objects, they are saved based on whether the implement a formal protocol. We have provided categories for most standard objects that tells SQLPO how to save those objects into the database, translate from the object to a table column, so the data is searchable. A property that is also a subclass of SQLitePersistentObjects will get stored in its own table, with a reference to that object&#x2019;s row and table being stored in this object. If there is no category (and the object is not also a subclass of SQLitePersistentObject, then it will look to see if the object conforms to NSCoding. If it does, it will archive the object into a blob. You must define properties for anything you want persisted into SQLite. Any non-persistent variables should not have properties. That&#x2019;s how SQLPO knows what to save and what not to save. Instance Variables without properties will not get saved to the database, nor will read-only properties.
  16. Here&#x2019;s the implementation of the class - nothing special, just typical stuff. You just implement it, and the SuperClass knows how to do pretty much everything. You could, of course (and probably should) create a designated initializer, but for simplicity&#x2019;s sake, I&#x2019;ve left it off here.
  17. All you do is allocate the object as you would any other object, assign values to its properties, and then call the save method. That one line is all it takes to save this object as a row in a table in a SQLite database. You don&#x2019;t need to create the database, you don&#x2019;t need to create the table, you just save.
  18. NSDictionary, NSArray, NSSet, and their mutable counterparts all follow these rules.
  19. In addition to the properties you define, there is one more special one, called pk, which stands for &#x201C;primary key&#x201D;. When you know the pk (and you&#x2019;ll see why you might later), loading an object is simple enough. What if you don&#x2019;t know the pk value, though?
  20. This will create an instance of your class for every row in the database. You might do this sometimes, but usually you don&#x2019;t want every objects.
  21. This method will return an array of all people with a last name that is equal to &#x201C;Washington&#x201D;.
  22. You can also use SQL pattern matching - using the % or _ wildcards (percent matches any number of characters, underscore matches just one character), this code would return everybody whose last name begins with &#x201C;Wash&#x201D;. Note: The bottom two examples will generate a compiler warning because the compiler won&#x2019;t be able to find the method. That&#x2019;s logical, since it doesn&#x2019;t exist - these methods are created dynamically at runtime. You can squelch the warning by creating a category on your own class in your class&#x2019; header file
  23. There&#x2019;s our category - add the declaration for any dynamic methods you use to a category like this, right in your class&#x2019; header file, and the compiler warnings go away.
  24. If you use this method, you are responsible for providing the correct SQL. It must start with &#x201C;WHERE&#x201D; and you must use the correct column names. Capitalized letters in camel case become lower-case with an underscore. But, you don&#x2019;t have to remember that, because there&#x2019;s a category on NSString that will do it for you. You can even specify an &#x201C;ORDER BY&#x201D; clause if you want the results returned in a specific order.
  25. If you use this method, you are responsible for providing the correct SQL. It must start with &#x201C;WHERE&#x201D; and you must use the correct column names. Capitalized letters in camel case become lower-case with an underscore. But, you don&#x2019;t have to remember that, because there&#x2019;s a category on NSString that will do it for you. You can even specify an &#x201C;ORDER BY&#x201D; clause if you want the results returned in a specific order.
  26. Don&#x2019;t guess! When in doubt about the column name, use the category - you&#x2019;ll be using the same code that we use to create the tables in the first place.
  27. There is also an instance method of the same name that can be called to delete an object from the database, but it&#x2019;s use is discourage and is going to be deprecated. Calling delete on an instance is problematic, because SQLPO maintains a map of all objects that have been loaded. It does this so that if you load the same object separately in two places, both places will be referring to the same object, rather than two separate objects created from the same source data. You should release the object before deleting it. If you don&#x2019;t, the object will continue to exist in memory after being deleted, and could end up getting unintentionally saved back to the database.
  28. For this, you should use the property name, not the column name. In this example, we&#x2019;re telling SQLPO to create two indexes, one on lastname, firstname, and pk (in that order), the other on birthdate, pk.
  29. Here is a potential problem. The iPhone does not have virtual memory in the same way that your Mac does. It won&#x2019;t write volatile pages of memory to the filesystem, and it only has 128 megs to work with. For everything. That means video ram, OS, everything. So, what do you think will happen when we load 1,000 people, each with a one-megapixel photo, into memory so that we can display them in a table?
  30. Here is a potential problem. The iPhone does not have virtual memory in the same way that your Mac does. It won&#x2019;t write volatile pages of memory to the filesystem, and it only has 128 megs to work with. For everything. That means video ram, OS, everything. So, what do you think will happen when we load 1,000 people, each with a one-megapixel photo, into memory so that we can display them in a table?
  31. Here is a potential problem. The iPhone does not have virtual memory in the same way that your Mac does. It won&#x2019;t write volatile pages of memory to the filesystem, and it only has 128 megs to work with. For everything. That means video ram, OS, everything. So, what do you think will happen when we load 1,000 people, each with a one-megapixel photo, into memory so that we can display them in a table?
  32. Yeah, crash and burn. With traditional object archiving, it would be complex to deal with this. SQLite lets us get information without loading our whole object into memory, however, and SQLPO makes it easy to do. In order to utilize this functionality, though, you need to understand a concept called &#x201C;paired arrays&#x201D;. If you&#x2019;ve set up a settings bundle for an application and used the MultiValue fields, you have seen paired arrays in action. To do that, you provide one array with the values to be displayed, and the other with the values that will actually be stored in the user defaults system.
  33. It may sound a little confusing, but it&#x2019;s really quite simple in practice. Let&#x2019;s take a look.
  34. So, just to be clear, the first object in the pks array will hold the primary key for the person whose first name is contained in the first object of the firstNames array and whose last name is contained in the first object of the lastNames array. Same goes for the second row, the third row, etc.
  35. In this code here, we&#x2019;re loading the arrays with information about all the people whose birthdate we know. We&#x2019;re getting their first name and last name so we can display it in a table, and we keep the primary keys so that if the user selects a row, we know which person to load and display.
  36. NSMutableArray has the ability to sort its contents based on a comparison method. But, if you sort the arrays, all of a sudden, you have a problem because the fifth object in one array, no longer necessarily corresponds to the fifth object in the other arrays.
  37. SQLPO provides a category on NSMutableArray that lets you sort an array and also sort all of its paired arrays so that they all stay in sync. That pretty much sums up the basics. You&#x2019;ve seen how to create, load, save, and delete objects and you&#x2019;ve seen how to use and sort paired arrays so that you can display data from all the objects in the database with having memory problems. Now, let&#x2019;s look at some of the more involved uses of the database.
  38. Here is how it sorts if we sort the firstNames array using sortArrayUsingSelector:withPairedMutableArrays: instead of separately sorting the three arrays.
  39. Do you want to know the sum or average value a field? In the old days, that would have involved iterating over all your objects and keeping a running count. Not so with SQLite. SQLite will do aggregations for you without having to load objects into memory, and it&#x2019;s very, very fast. SQLitePersistentObject has a convenience method for getting aggregate values. It returns a single floating point value returned from the SQL query you supply. Here is how you might find the average age of all the people in the database, or of just a subset. There are many aggregation methods, much like you might find in Numbers or Excel, including min, max, sum, average, rounding, etc.
  40. SQLitePersistentObjects also creates dynamic methods at runtime for getting aggregations. Currently average, sum, count, min, and max are supported, either for the entire population, or for a subset by specifying &#x201C;withCriteria&#x201D; and providing a SQL where clause. Additional aggregations are coming soon, including min, max, maybe median. Because these are dynamic methods, will get compiler warnings about them. You can squelch them with a category, the way I showed you earlier with the findBy methods.
  41. Let&#x2019;s say you&#x2019;ve got an object out there that you want to get saved in the database, but you want it be searchable, not stored as a blob, but that object doesn&#x2019;t conform to SQLitePersistence. What can you do? Answer is easy - create a category to conform that class to SQLitePersistence. Here&#x2019;s that protocol. These methods define how SQLPO talks to an object to determine if it can be saved in a column, and how to actually save it. The first method is used to indicate that this object can be stored in SQLite. Simply return YES in that method to indicate that your object should be saved. The second method indicates the type of column that should be used. It should return TEXT, INTEGER, REAL, or BLOB. The third method is used to ask the object if it needs to be stored in a BLOB. Now, this probably seems a little redundant, since BLOB was one of the options in the previous method, but simply for performance, it&#x2019;s faster to specify a BOOL than it is to constantly be doing string comparisons. If you return YES here, you should return BLOB in the columnTypeForObjectStorage method, although SQLite is pretty cool about datatypes, and will convert as necessary. The last four methods serve the same purpose - one is used for objects that return YES to shouldBeStoredInBlob, and the other is used if the answer is NO. If it&#x2019;s going to be stored in a BLOB, you have to provide the information in an NSData to make sure it doesn&#x2019;t get altered in any way. Otherwise, you can return an object. When in doubt, return an NSString, but you can also use NSNumber, or pretty much any other object that prints its value when sent the description method.
  42. The project currently has no formal roadmap. Development is driven now by the specific needs of the project members. When one of us needs a certain bit of functionality for a project we&#x2019;re working on, we propose it to the group, vet it out for possible problems, and then it gets implemented. Very informal. At some point, we plan to sit down and come up with something more formal, and more long-term, but probably won&#x2019;t be for a few months, given how busy most iPhone developers are right now. Some of the things that have been discussed include implementing a validation architecture so that objects can do more robust validation, such things as enforcing unique fields or combinations of fields, notifications to the object that a save has occurred or will occur, and possibly even giving the object the ability to conditionally cancel or prevent a save. Transient properties are properties that don&#x2019;t get saved to the database. Currently read-only properties are treated as transient, but there is beta functionality in the system to allow other properties to be specified as transient. There&#x2019;s always room for performance optimizations. There are several places in the code where there&#x2019;s room to eke out more performance, and we&#x2019;ll visit those once we&#x2019;ve done benchmarking and have a real view of where our slowdowns are. Rollback isn&#x2019;t much of an issue for most iPhone applications, since we tend to make the user commit changes fairly frequently. However, to get wider acceptance on the Mac
  43. Honestly, we don&#x2019;t have benchmarks. We haven&#x2019;t done rigorous testing or benchmarking yet. All we have is anecdotal evidence from using it in a handful of applications. So far, I have yet to see any issues with performance compared to hand-coding the SQL. Now, we know it takes more processing power to dynamically generate SQL on the fly than it does to execute hard-coded SQL stored in string constants. That&#x2019;s a fact. We also know there are places in the code that can be optimized to work faster. But, it seems to be fast enough for the vast majority of uses on the iPhone.
  44. Honestly, we don&#x2019;t have benchmarks. We haven&#x2019;t done rigorous testing or benchmarks. All we have is anecdotal evidence from using it in a handful of applications. So far, I have yet to see any issues with performance compared to hand-coding the SQL. Now, we know it takes more processing power than hard-coded SQL. That&#x2019;s a fact. We also know there are places in the code that can be optimized. But, it seems to be fast enough for the vast majority of uses on the iPhone.