nano-store 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/README.md +8 -4
  2. data/Rakefile +1 -1
  3. data/lib/nano_store.rb +2 -4
  4. data/lib/nano_store/version.rb +1 -1
  5. data/spec/model_spec.rb +14 -0
  6. data/spec/spec_helper.rb +4 -0
  7. data/vendor/Podfile.lock +4 -4
  8. data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoGlobals.h +3 -1
  9. data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoPredicate.h +5 -5
  10. data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoSearch.h +5 -3
  11. data/vendor/Pods/BuildHeaders/NanoStore/NSFNanoSortDescriptor.h +1 -1
  12. data/vendor/Pods/BuildHeaders/NanoStore/NanoStore.h +36 -0
  13. data/vendor/Pods/Documentation/NanoStore/docset-installed.txt +2 -2
  14. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Info.plist +3 -3
  15. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoBag.html +2 -2
  16. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoEngine.html +2 -2
  17. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoExpression.html +2 -2
  18. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoObject.html +2 -2
  19. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoPredicate.html +7 -7
  20. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoResult.html +2 -2
  21. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoSearch.html +66 -5
  22. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoSortDescriptor.html +3 -3
  23. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFNanoStore.html +2 -2
  24. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Classes/NSFOrderedDictionary.html +2 -2
  25. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/Protocols/NSFNanoObjectProtocol.html +2 -2
  26. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/css/styles.css +0 -0
  27. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/hierarchy.html +5 -5
  28. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Documents/index.html +5 -5
  29. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Nodes.xml +1 -1
  30. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Tokens5.xml +6 -6
  31. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Tokens7.xml +24 -2
  32. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/Tokens8.xml +2 -2
  33. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/docSet.dsidx +0 -0
  34. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/docSet.skidx +0 -0
  35. data/vendor/Pods/Documentation/NanoStore/docset/Contents/Resources/docSet.toc +0 -0
  36. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoBag.html +2 -2
  37. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoEngine.html +2 -2
  38. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoExpression.html +2 -2
  39. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoObject.html +2 -2
  40. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoPredicate.html +7 -7
  41. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoResult.html +2 -2
  42. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoSearch.html +66 -5
  43. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoSortDescriptor.html +3 -3
  44. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFNanoStore.html +2 -2
  45. data/vendor/Pods/Documentation/NanoStore/html/Classes/NSFOrderedDictionary.html +2 -2
  46. data/vendor/Pods/Documentation/NanoStore/html/Protocols/NSFNanoObjectProtocol.html +2 -2
  47. data/vendor/Pods/Documentation/NanoStore/html/css/styles.css +0 -0
  48. data/vendor/Pods/Documentation/NanoStore/html/hierarchy.html +5 -5
  49. data/vendor/Pods/Documentation/NanoStore/html/index.html +5 -5
  50. data/vendor/Pods/Headers/NanoStore/NSFNanoGlobals.h +3 -1
  51. data/vendor/Pods/Headers/NanoStore/NSFNanoPredicate.h +5 -5
  52. data/vendor/Pods/Headers/NanoStore/NSFNanoSearch.h +5 -3
  53. data/vendor/Pods/Headers/NanoStore/NSFNanoSortDescriptor.h +1 -1
  54. data/vendor/Pods/Headers/NanoStore/NanoStore.h +36 -0
  55. data/vendor/Pods/NanoStore/Classes/Advanced/NSFNanoEngine.m +40 -49
  56. data/vendor/Pods/NanoStore/Classes/Advanced/NSFNanoResult.m +42 -53
  57. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoBag.m +80 -89
  58. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoExpression.m +11 -13
  59. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoGlobals.h +3 -1
  60. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoGlobals.m +1 -0
  61. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoObject.m +34 -29
  62. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoPredicate.h +5 -5
  63. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoPredicate.m +43 -34
  64. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSearch.h +5 -3
  65. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSearch.m +171 -97
  66. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSortDescriptor.h +1 -1
  67. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoSortDescriptor.m +13 -12
  68. data/vendor/Pods/NanoStore/Classes/Public/NSFNanoStore.m +92 -86
  69. data/vendor/Pods/NanoStore/Classes/Public/NanoStore.h +36 -0
  70. data/vendor/Pods/Pods-resources.sh +8 -4
  71. data/vendor/Pods/Pods.bridgesupport +109 -101
  72. metadata +5 -5
@@ -75,7 +75,7 @@
75
75
  @interface NSFNanoSortDescriptor : NSObject
76
76
 
77
77
  /** * The property key to use when performing a comparison */
78
- @property (nonatomic, readonly) NSString *attribute;
78
+ @property (nonatomic, copy, readonly) NSString *attribute;
79
79
  /** * The property to indicate whether the comparison should be performed in ascending mode */
80
80
  @property (nonatomic, readonly) BOOL isAscending;
81
81
 
@@ -29,15 +29,16 @@
29
29
  #import "NSFOrderedDictionary.h"
30
30
  #import "NSFNanoObject_Private.h"
31
31
 
32
- @implementation NSFNanoSortDescriptor
33
- {
34
- /** \cond */
35
- NSString *attribute;
36
- BOOL isAscending;
37
- /** \endcond */
38
- }
32
+ @interface NSFNanoSortDescriptor ()
33
+
34
+ /** \cond */
35
+ @property (nonatomic, copy, readwrite) NSString *attribute;
36
+ @property (nonatomic, readwrite) BOOL isAscending;
37
+ /** \endcond */
39
38
 
40
- @synthesize attribute, isAscending;
39
+ @end
40
+
41
+ @implementation NSFNanoSortDescriptor
41
42
 
42
43
  + (NSFNanoSortDescriptor *)sortDescriptorWithAttribute:(NSString *)theAttribute ascending:(BOOL)ascending
43
44
  {
@@ -52,8 +53,8 @@
52
53
  userInfo:nil]raise];
53
54
 
54
55
  if ((self = [super init])) {
55
- attribute = [theAttribute copy];
56
- isAscending = ascending;
56
+ _attribute = theAttribute;
57
+ _isAscending = ascending;
57
58
  }
58
59
 
59
60
  return self;
@@ -76,8 +77,8 @@
76
77
  NSFOrderedDictionary *values = [NSFOrderedDictionary new];
77
78
 
78
79
  values[@"Sort descriptor address"] = [NSString stringWithFormat:@"%p", self];
79
- values[@"Attribute"] = attribute;
80
- values[@"Is ascending?"] = (isAscending ? @"YES" : @"NO");
80
+ values[@"Attribute"] = _attribute;
81
+ values[@"Is ascending?"] = (_isAscending ? @"YES" : @"NO");
81
82
 
82
83
  return values;
83
84
  }
@@ -6,7 +6,7 @@
6
6
 
7
7
  Redistribution and use in source and binary forms, with or without modification, are permitted
8
8
  provided that the following conditions are met:
9
-
9
+
10
10
  * Redistributions of source code must retain the above copyright notice, this list of conditions
11
11
  and the following disclaimer.
12
12
  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
@@ -33,20 +33,21 @@
33
33
 
34
34
  #include <stdlib.h>
35
35
 
36
+ @interface NSFNanoStore ()
37
+
38
+ /** \cond */
39
+ @property (nonatomic, strong, readwrite) NSFNanoEngine *nanoStoreEngine;
40
+ @property (nonatomic, readwrite) BOOL hasUnsavedChanges;
41
+ @property (nonatomic) NSMutableArray *addedObjects;
42
+ @property (nonatomic) BOOL isOurTransaction;
43
+ @property (nonatomic, assign) sqlite3_stmt *insertDeleteKeysStatement;
44
+ @property (nonatomic, assign) sqlite3_stmt *storeValuesStatement;
45
+ @property (nonatomic, assign) sqlite3_stmt *storeKeysStatement;
46
+ /** \endcond */
47
+
48
+ @end
49
+
36
50
  @implementation NSFNanoStore
37
- {
38
- @protected
39
- NSFNanoEngine *nanoStoreEngine;
40
- NSFEngineProcessingMode nanoEngineProcessingMode;
41
- NSUInteger saveInterval;
42
-
43
- /** \cond */
44
- NSMutableArray *addedObjects;
45
- BOOL _isOurTransaction;
46
- sqlite3_stmt *_storeValuesStatement;
47
- sqlite3_stmt *_storeKeysStatement;
48
- /** \endcond */
49
- }
50
51
 
51
52
  @synthesize nanoStoreEngine;
52
53
  @synthesize nanoEngineProcessingMode;
@@ -101,10 +102,11 @@
101
102
  _isOurTransaction = NO;
102
103
  saveInterval = 1;
103
104
 
105
+ _insertDeleteKeysStatement = NULL;
104
106
  _storeValuesStatement = NULL;
105
107
  _storeKeysStatement = NULL;
106
108
 
107
- addedObjects = [[NSMutableArray alloc]initWithCapacity:saveInterval];
109
+ _addedObjects = [[NSMutableArray alloc]initWithCapacity:saveInterval];
108
110
  }
109
111
 
110
112
  return self;
@@ -113,8 +115,6 @@
113
115
  - (void)dealloc
114
116
  {
115
117
  [self closeWithError:nil];
116
-
117
-
118
118
  }
119
119
 
120
120
  - (NSString *)filePath
@@ -204,7 +204,7 @@
204
204
 
205
205
  - (BOOL)hasUnsavedChanges
206
206
  {
207
- return ([addedObjects count] > 0);
207
+ return ([_addedObjects count] > 0);
208
208
  }
209
209
 
210
210
  #pragma mark -
@@ -225,11 +225,12 @@
225
225
  }
226
226
 
227
227
  if ([someObjects count] == 0) {
228
- if (nil != outError)
228
+ if (nil != outError) {
229
229
  *outError = [NSError errorWithDomain:NSFDomainKey
230
230
  code:NSFNanoStoreErrorKey
231
231
  userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: ([someObjects count] == 0)", [self class], NSStringFromSelector(_cmd)]
232
232
  forKey:NSLocalizedFailureReasonErrorKey]];
233
+ }
233
234
  return NO;
234
235
  }
235
236
 
@@ -240,32 +241,17 @@
240
241
  // If it's a bag, make sure the name is unique
241
242
  if (YES == [object isKindOfClass:[NSFNanoBag class]]) {
242
243
  NSFNanoBag *bag = (NSFNanoBag *)object;
243
- NSString *bagName = bag.name;
244
- if (bagName.length > 0) {
245
- NSFNanoBag *bagWithSameName = [self bagWithName:bagName];
246
- if (nil != bagWithSameName) {
247
- if (nil != outError) {
248
- *outError = [NSError errorWithDomain:NSFDomainKey
249
- code:NSFNanoStoreErrorKey
250
- userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: a bag named '%@' already exists.", [self class], NSStringFromSelector(_cmd), bagName]
251
- forKey:NSLocalizedFailureReasonErrorKey]];
252
-
253
- return NO;
254
- }
255
- }
256
- }
257
-
258
244
 
259
245
  // If it's a bag, process it first by gathering. If it's not dirty, there's no need to save...
260
- if (YES == [object hasUnsavedChanges]) {
246
+ if (YES == [bag hasUnsavedChanges]) {
261
247
  NSError *error = nil;
262
248
 
263
249
  // Associate the bag to this store
264
- if (nil == [object store]) {
250
+ if (nil == [bag store]) {
265
251
  [object _setStore:self];
266
252
  }
267
253
 
268
- if (NO == [object _saveInStore:self error:&error]) {
254
+ if (NO == [bag _saveInStore:self error:&error]) {
269
255
  [[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
270
256
  reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [error localizedDescription]]
271
257
  userInfo:nil]raise];
@@ -290,7 +276,6 @@
290
276
 
291
277
  BOOL success = [self _addObjectsFromArray:nonBagObjects forceSave:NO error:outError];
292
278
 
293
-
294
279
  return success;
295
280
  }
296
281
 
@@ -321,31 +306,38 @@
321
306
  NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"CREATE TEMP TABLE %@(x);", NSF_Private_ToDeleteTableKey];
322
307
  [nanoStoreEngine executeSQL:theSQLStatement];
323
308
 
324
- sqlite3_stmt *statement;
325
- theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@ VALUES (?);", NSF_Private_ToDeleteTableKey];
326
- BOOL success = [self _prepareSQLite3Statement:&statement theSQLStatement:theSQLStatement];
327
-
328
- if (success) {
329
- for (NSString *key in someKeys) {
330
- int status = sqlite3_reset (statement);
331
- if (SQLITE_OK != status) {
332
- break;
333
- }
334
-
335
- // Bind and execute the statement...
336
- status = sqlite3_bind_text ( statement, 1, [key UTF8String], -1, SQLITE_STATIC);
337
-
338
- // Since we're operating with extended result code support, extract the bits
339
- // and obtain the regular result code
340
- // For more info check: http://www.sqlite.org/c3ref/c_ioerr_access.html
341
-
342
- status = [NSFNanoEngine NSFP_stripBitsFromExtendedResultCode:status];
343
-
344
- if (SQLITE_OK == status) {
345
- [self _executeSQLite3StepUsingSQLite3Statement:statement];
309
+ if (NULL == _insertDeleteKeysStatement) {
310
+ theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@ VALUES (?);", NSF_Private_ToDeleteTableKey];
311
+ BOOL success = [self _prepareSQLite3Statement:&_insertDeleteKeysStatement theSQLStatement:theSQLStatement];
312
+ if (NO == success) {
313
+ if (nil != outError) {
314
+ *outError = [NSError errorWithDomain:NSFDomainKey
315
+ code:NSFNanoStoreErrorKey
316
+ userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _insertDeleteKeysStatement.", [self class], NSStringFromSelector(_cmd)]
317
+ forKey:NSLocalizedFailureReasonErrorKey]];
346
318
  }
319
+ return NO;
320
+ }
321
+ }
322
+
323
+ for (NSString *key in someKeys) {
324
+ int status = sqlite3_reset (_insertDeleteKeysStatement);
325
+ if (SQLITE_OK != status) {
326
+ break;
327
+ }
328
+
329
+ // Bind and execute the statement...
330
+ status = sqlite3_bind_text ( _insertDeleteKeysStatement, 1, [key UTF8String], -1, SQLITE_STATIC);
331
+
332
+ // Since we're operating with extended result code support, extract the bits
333
+ // and obtain the regular result code
334
+ // For more info check: http://www.sqlite.org/c3ref/c_ioerr_access.html
335
+
336
+ status = [NSFNanoEngine NSFP_stripBitsFromExtendedResultCode:status];
337
+
338
+ if (SQLITE_OK == status) {
339
+ [self _executeSQLite3StepUsingSQLite3Statement:_insertDeleteKeysStatement];
347
340
  }
348
- sqlite3_finalize(statement);
349
341
  }
350
342
 
351
343
  _NSFLog(@" Before removing the keys to be stored from NSFKeys...");
@@ -575,7 +567,7 @@
575
567
 
576
568
  - (void)discardUnsavedChanges
577
569
  {
578
- [addedObjects removeAllObjects];
570
+ [_addedObjects removeAllObjects];
579
571
  }
580
572
 
581
573
  // ----------------------------------------------
@@ -677,11 +669,12 @@
677
669
  return NO;
678
670
 
679
671
  if ([[self nanoStoreEngine]isTransactionActive]) {
680
- if (nil != outError)
672
+ if (nil != outError) {
681
673
  *outError = [NSError errorWithDomain:NSFDomainKey
682
674
  code:NSFNanoStoreErrorKey
683
675
  userInfo:[NSDictionary dictionaryWithObject:@"Cannot backup store. A transaction is still open."
684
676
  forKey:NSLocalizedDescriptionKey]];
677
+ }
685
678
  return NO;
686
679
  }
687
680
 
@@ -729,31 +722,38 @@
729
722
  NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@(%@, %@, %@, %@) VALUES (?,?,?,?);", NSFValues, NSFKey, NSFAttribute, NSFValue, NSFDatatype];
730
723
  hasInitializationSucceeded = [self _prepareSQLite3Statement:&_storeValuesStatement theSQLStatement:theSQLStatement];
731
724
 
732
- if ((nil != outError) && (NO == hasInitializationSucceeded)) {
733
- *outError = [NSError errorWithDomain:NSFDomainKey
734
- code:NSFNanoStoreErrorKey
735
- userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _storeValuesStatement.", [self class], NSStringFromSelector(_cmd)]
736
- forKey:NSLocalizedFailureReasonErrorKey]];
725
+ if (NO == hasInitializationSucceeded) {
726
+ if (nil != outError) {
727
+ *outError = [NSError errorWithDomain:NSFDomainKey
728
+ code:NSFNanoStoreErrorKey
729
+ userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _storeValuesStatement.", [self class], NSStringFromSelector(_cmd)]
730
+ forKey:NSLocalizedFailureReasonErrorKey]];
731
+ }
732
+ return NO;
737
733
  }
738
734
  }
739
735
 
740
- if ((NULL == _storeKeysStatement) && (YES == hasInitializationSucceeded)) {
736
+ if (NULL == _storeKeysStatement) {
741
737
  NSString *theSQLStatement = [[NSString alloc]initWithFormat:@"INSERT INTO %@(%@, %@, %@, %@) VALUES (?,?,?,?);", NSFKeys, NSFKey, NSFKeyedArchive, NSFCalendarDate, NSFObjectClass];
742
738
  hasInitializationSucceeded = [self _prepareSQLite3Statement:&_storeKeysStatement theSQLStatement:theSQLStatement];
743
739
 
744
- if ((nil != outError) && (NO == hasInitializationSucceeded)) {
745
- *outError = [NSError errorWithDomain:NSFDomainKey
746
- code:NSFNanoStoreErrorKey
747
- userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _storeKeysStatement.", [self class], NSStringFromSelector(_cmd)]
748
- forKey:NSLocalizedFailureReasonErrorKey]];
740
+ if (NO == hasInitializationSucceeded) {
741
+ if (nil != outError) {
742
+ *outError = [NSError errorWithDomain:NSFDomainKey
743
+ code:NSFNanoStoreErrorKey
744
+ userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %@]: failed to prepare _storeKeysStatement.", [self class], NSStringFromSelector(_cmd)]
745
+ forKey:NSLocalizedFailureReasonErrorKey]];
746
+ }
747
+ return NO;
749
748
  }
750
749
  }
751
750
 
752
- return hasInitializationSucceeded;
751
+ return YES;
753
752
  }
754
753
 
755
754
  - (void)_releasePreparedStatements
756
755
  {
756
+ if (_insertDeleteKeysStatement != NULL) { sqlite3_finalize(_insertDeleteKeysStatement);_insertDeleteKeysStatement = NULL; }
757
757
  if (_storeValuesStatement != NULL) { sqlite3_finalize(_storeValuesStatement);_storeValuesStatement = NULL; }
758
758
  if (_storeKeysStatement != NULL) { sqlite3_finalize(_storeKeysStatement);_storeKeysStatement = NULL; }
759
759
  }
@@ -1120,10 +1120,10 @@
1120
1120
  - (BOOL)_addObjectsFromArray:(NSArray *)someObjects forceSave:(BOOL)forceSave error:(out NSError **)outError
1121
1121
  {
1122
1122
  // Collect the objects
1123
- [addedObjects addObjectsFromArray:someObjects];
1123
+ [_addedObjects addObjectsFromArray:someObjects];
1124
1124
 
1125
1125
  // No need to continue if there's nothing to be saved
1126
- NSUInteger unsavedObjectsCount = [addedObjects count];
1126
+ NSUInteger unsavedObjectsCount = [_addedObjects count];
1127
1127
  if (0 == unsavedObjectsCount) {
1128
1128
  return YES;
1129
1129
  }
@@ -1138,9 +1138,9 @@
1138
1138
 
1139
1139
  // Remove all objects non conforming with the NSFNanoObjectProtocol
1140
1140
  while ( i-- ) {
1141
- id object = [addedObjects objectAtIndex:i];
1141
+ id object = [_addedObjects objectAtIndex:i];
1142
1142
  if (NO == [object conformsToProtocol:@protocol(NSFNanoObjectProtocol)]) {
1143
- [addedObjects removeObjectAtIndex:i];
1143
+ [_addedObjects removeObjectAtIndex:i];
1144
1144
  i--;
1145
1145
  continue;
1146
1146
  }
@@ -1155,7 +1155,7 @@
1155
1155
  }
1156
1156
 
1157
1157
  // Recalculate how many elements we have left
1158
- unsavedObjectsCount = [addedObjects count];
1158
+ unsavedObjectsCount = [_addedObjects count];
1159
1159
 
1160
1160
  if (unsavedObjectsCount > 0) {
1161
1161
  NSError *localOutError = nil;
@@ -1179,7 +1179,9 @@
1179
1179
  self.saveInterval = 1;
1180
1180
  }
1181
1181
 
1182
- for (id object in addedObjects) {
1182
+ NSString *errorMessage = @"<error reason unknown>";
1183
+
1184
+ for (id object in _addedObjects) {
1183
1185
  @autoreleasepool {
1184
1186
  // If the object was originally created by storing a class not recognized by this process, honor it and store it with the right class string.
1185
1187
  NSString *className = nil;
@@ -1193,8 +1195,9 @@
1193
1195
  }
1194
1196
 
1195
1197
  if (NO == [self _storeDictionary:[object nanoObjectDictionaryRepresentation] forKey:[(id)object nanoObjectKey] forClassNamed:className error:outError]) {
1198
+ if (nil != outError) errorMessage = [*outError localizedDescription];
1196
1199
  [[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
1197
- reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
1200
+ reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), errorMessage]
1198
1201
  userInfo:nil]raise];
1199
1202
  } else {
1200
1203
  SEL setStoreSelector = @selector(setStore:);
@@ -1211,16 +1214,18 @@
1211
1214
  // Commit every 'saveInterval' interations...
1212
1215
  if ((0 == i % self.saveInterval) && transactionStartedHere) {
1213
1216
  if (NO == [self commitTransactionAndReturnError:outError]) {
1217
+ if (nil != outError) errorMessage = [*outError localizedDescription];
1214
1218
  [[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
1215
- reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
1219
+ reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), errorMessage]
1216
1220
  userInfo:nil]raise];
1217
1221
  }
1218
1222
 
1219
1223
  if (YES == transactionStartedHere) {
1220
1224
  transactionStartedHere = [self beginTransactionAndReturnError:outError];
1221
1225
  if (NO == transactionStartedHere) {
1226
+ if (nil != outError) errorMessage = [*outError localizedDescription];
1222
1227
  [[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
1223
- reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
1228
+ reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), errorMessage]
1224
1229
  userInfo:nil]raise];
1225
1230
  }
1226
1231
  }
@@ -1231,8 +1236,9 @@
1231
1236
  // Commit the changes
1232
1237
  if (transactionStartedHere) {
1233
1238
  if (NO == [self commitTransactionAndReturnError:outError]) {
1239
+ if (nil != outError) errorMessage = [*outError localizedDescription];
1234
1240
  [[NSException exceptionWithName:NSFNanoStoreUnableToManipulateStoreException
1235
- reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), [*outError localizedDescription]]
1241
+ reason:[NSString stringWithFormat:@"*** -[%@ %@]: %@", [self class], NSStringFromSelector(_cmd), errorMessage]
1236
1242
  userInfo:nil]raise];
1237
1243
  }
1238
1244
  }
@@ -1241,7 +1247,7 @@
1241
1247
  double ratio = unsavedObjectsCount/secondsStoring;
1242
1248
  _NSFLog(@" Done. Storing the objects took %.3f seconds (%.0f keys/sec.)", secondsStoring, ratio);
1243
1249
 
1244
- [addedObjects removeAllObjects];
1250
+ [_addedObjects removeAllObjects];
1245
1251
  }
1246
1252
 
1247
1253
  return YES;
@@ -64,6 +64,13 @@
64
64
  - iOS library runs on the device and simulator
65
65
  - ARC compliant
66
66
 
67
+ @section latest_changes Latest changes
68
+ v2.5 - January 1, 2013
69
+
70
+ Starting with v2.5, the plist mechanism has been replaced with NSKeyedArchiver. There are several reasons for it: it's more compact, faster and uses less memory. Perhaps the most important reason is that it opens the possibility to store other data types.
71
+
72
+ NSNull is now supported. Big thanks to Wanny (https://github.com/mrwanny) for taking the time to improve this section of NanoStore.
73
+
67
74
  @section installation_sec Installation
68
75
 
69
76
  Building NanoStore is very easy. Just follow these steps:
@@ -423,6 +430,35 @@
423
430
  [sortByLastName release];
424
431
  @endcode
425
432
 
433
+ @section paging_limit_sec Paging using Limit and Offset
434
+ SQLite provides a really cool feature called OFFSET that is usually used with a LIMIT clause.
435
+
436
+ The LIMIT clause is used to limit the number of results returned in a SQL statement. So if you have 1000 rows in table, but only want to return the first 10, you would do something like this:
437
+ @code
438
+ SELECT column FROM table LIMIT 10
439
+ @endcode
440
+ Now suppose you wanted to show results 11-20. With the OFFSET keyword it's just as easy. The following query will do:
441
+ @code
442
+ SELECT column FROM table LIMIT 10 OFFSET 10
443
+ @endcode
444
+ Using pagination is also quite easy with NanoStore. This example based on one of the unit tests provided with the NanoStore distro:
445
+ @code
446
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
447
+
448
+ // Assume we have added objects to the store
449
+
450
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:nanoStore];
451
+ search.value = @"Barcelona";
452
+ search.match = NSFEqualTo;
453
+ search.limit = 5;
454
+ search.offset = 3;
455
+
456
+ NSDictionary *searchResults = [search searchObjectsWithReturnType:NSFReturnObjects error:nil];
457
+
458
+ // Assuming the query matches some results, NanoStore should have retrieved
459
+ // the first 5 records right after the 3rd one from the result set.
460
+ @endcode
461
+
426
462
  @section performancetips_sec Performance Tips
427
463
 
428
464
  NanoStore by defaults saves every object to disk one by one. To speed up inserts and edited objects, increase NSFNanoStore's \link NSFNanoStore::saveInterval saveInterval \endlink property.