diff --git a/Sources/ChuzzleKit.m b/Sources/ChuzzleKit.m index 429cfb8..04c6c9a 100644 --- a/Sources/ChuzzleKit.m +++ b/Sources/ChuzzleKit.m @@ -17,20 +17,19 @@ - (id)chuzzle { if (self.count == 0) { return nil; } - id objs[self.count]; - id keys[self.count]; - NSUInteger x = 0; + NSMutableArray* objs = [NSMutableArray arrayWithCapacity:self.count]; + NSMutableArray* keys = [NSMutableArray arrayWithCapacity:self.count]; for (id key in self) { id obj = self[key]; - if ([obj respondsToSelector:@selector(chuzzle)]) - obj = [obj chuzzle]; + if ([obj respondsToSelector:@selector(chuzzle)]) { + obj = [obj chuzzle]; + } if (obj) { - objs[x] = obj; - keys[x] = key; - x += 1; + [objs addObject:obj]; + [keys addObject:key]; } } - return x == 0 ? nil : [NSDictionary dictionaryWithObjects:objs forKeys:keys count:x]; + return (objs.count == 0) ? nil : [NSDictionary dictionaryWithObjects:objs forKeys:keys]; } @end @@ -42,15 +41,16 @@ - (instancetype)chuzzle { if (self.count == 0) { return nil; } - id objs[self.count]; - NSUInteger x = 0; + NSMutableArray* result = [NSMutableArray arrayWithCapacity:self.count]; for (__strong id obj in self) { - if ([obj respondsToSelector:@selector(chuzzle)]) - obj = [obj chuzzle]; - if (obj) - objs[x++] = obj; + if ([obj respondsToSelector:@selector(chuzzle)]) { + obj = [obj chuzzle]; + } + if (obj) { + [result addObject:obj]; + } } - return x == 0 ? nil : [NSArray arrayWithObjects:objs count:x]; + return result.count == 0 ? nil : [NSArray arrayWithArray:result]; } @end diff --git a/Tests/ChuzzleTests.m b/Tests/ChuzzleTests.m index fa8472d..8fe2883 100644 --- a/Tests/ChuzzleTests.m +++ b/Tests/ChuzzleTests.m @@ -23,5 +23,19 @@ - (void)test_nsobject { id o = [NSObject new]; XCTAssertEqual(o, [o chuzzle]); } +- (void)test_giant_array { + // using a very large number of objectcs to illustrate the problem + // and make the test trip on powerful desktop machines, but issues + // would obviously manifest sooner on mobile devices with less memory + NSUInteger size = 50000000; + NSMutableArray* a = [NSMutableArray arrayWithCapacity:size]; + for (int i = 0; i < size; i++) { + [a addObject:i % 2 ? @(i) : NSNull.null]; + } + a = [NSArray arrayWithArray:a]; + NSArray* b; + XCTAssertNoThrow(b = a.chuzzle); + XCTAssertEqual(b.count, a.count / 2); +} @end