1. TumbleOn
  2. Untitled project
  3. TumbleOn-Utils

Commits

Jason Baker  committed a64036c

Creating CocoaPod

  • Participants
  • Parent commits a3f0c16
  • Branches master

Comments (0)

Files changed (49)

File Classes/FileUtil.h

View file
+/*
+ 
+ FileUtil
+ 
+ A collection of file IO and filename related utilities.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface FileUtil : NSObject
+
+// get the basename for a file from the given string, i.e. "FileUtil" from "FileUtil.h"
++ (NSString *) baseName:(NSString *)fileName;
+
+// get the extension for a file from the given string, i.e. "h" from "FileUtil.h"
++ (NSString *) extension:(NSString*)fileName;
+
+// load a file from disk, i.e.:
+// NSString * html = [FileUtil loadFile:@"somefile.html"];
++ (NSString *) loadFile:(NSString *)fileName;
+
+// deserialize a NSCoding compliant object (with initWithCoder:) from the given file path
++ (NSObject *) loadObjectFromDisk:(NSString *)fileName;
+
+// serialize a NSCoding compliant object (with encodeWithCoder:) to a given file path
++ (void) saveObjectToFile:(NSString *)fileName object:(NSObject*)object;
+
+
+@end

File Classes/FileUtil.m

View file
+/*
+ 
+ FileUtil
+ 
+ A collection of file IO and filename related utilities.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "FileUtil.h"
+
+@implementation FileUtil
+
++ (NSString *) baseName:(NSString *)fileName {
+    if (fileName == nil) {
+        return nil;
+    }
+    NSRange range = [fileName rangeOfString:@"."];
+    if (range.location == NSNotFound || (range.location + range.length) >= fileName.length) { 
+        return nil;
+    }
+    return [fileName substringToIndex:range.location];    
+}
+
++ (NSString *) extension:(NSString*)fileName {
+    if (fileName == nil) {
+        return nil;
+    }
+    NSRange range = [fileName rangeOfString:@"."];
+    if (range.location == NSNotFound || (range.location + range.length) >= fileName.length) { 
+        return nil;
+    }    
+    return [fileName substringFromIndex:range.location +1];    
+}
+
++ (NSString *) loadFile:(NSString *)fileName {    
+    NSString * baseName = [FileUtil baseName:fileName];
+    NSString * extension = [FileUtil extension:fileName];
+    NSString * filePath = [[NSBundle mainBundle] pathForResource:baseName ofType:extension];  
+    if (!filePath) {
+        NSLog(@"File Util Error, Couldn't find file: %@", fileName);
+        return nil;
+    }    
+    NSString * fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];  
+    if (!fileContents) {
+        NSLog(@"File Util Error, Couldn't load file: %@", fileName);
+        return nil;
+    }    
+    return fileContents;
+}
+
++ (NSObject *) loadObjectFromDisk:(NSString *)fileName {
+    NSObject * object = nil;
+    NSString *filePath = [FileUtil dataFilePath:fileName];
+    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
+        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
+        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
+        object = [unarchiver decodeObjectForKey:@"Data"];
+        [unarchiver finishDecoding];
+    }
+    return object;
+}
+
++ (void) saveObjectToFile:(NSString *)fileName object:(NSObject*)object {
+    NSDate * startTime = [NSDate date];
+    NSMutableData *data = [[NSMutableData alloc] init];
+    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
+    [archiver encodeObject:object forKey:@"Data"];
+    [archiver finishEncoding];
+    [data writeToFile:[FileUtil dataFilePath:fileName] atomically:YES];
+    long timePassed_ms = (long) ([startTime timeIntervalSinceNow] * -1000.0);
+    NSMutableDictionary * params = [NSMutableDictionary dictionary];
+    int length = [data length];
+    [params setValue:[NSNumber numberWithLong:timePassed_ms] forKey:@"time_elapsed"];
+    [params setValue:[NSNumber numberWithLong:length] forKey:@"bytes"];
+    [params setValue:fileName forKey:@"file"];
+    NSLog(@"object saved to file: %@ in %ld ms, %d bytes", fileName, timePassed_ms, length);
+}
+
++ (NSString *)dataFilePath:(NSString *)filename {
+	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+	NSString *documentsDirectory = [paths objectAtIndex:0];
+	return [documentsDirectory stringByAppendingPathComponent: filename];
+}
+
+@end

File Classes/FrameUtils.h

View file
+/*
+
+FrameUtils.h
+
+A collection of utilities that simplify common Objective C CGRect/Frame 
+operations such as resizing, moving, centering, debug logging, and more.
+
+USAGE INSTRUCTIONS
+
+Using this class is simple. Simply include the source code from the
+FrameUtils.zip file in your Objective C project, then import this file in
+any file where you would like to use the methods provided by class.
+
+USAGE EXAMPLES
+
+#move a frame to position 0,0
+CGRect movedFrame = [FrameUtils frame:oldFrame moveToX:0 y:0];
+
+#move a frame left by 50 pixels
+CGRect movedFrame = [FrameUtils frame:oldFrame moveByXDelta:-50];
+
+#resize a frame to 50x100
+CGRect resizedFrame = [FrameUtils frame:oldFrame resizeToWidth:50 height:100];
+
+#resize a frame to be 75 pixels wider
+CGRect resizedFrame = [FrameUtils frame:oldFrame resizeByWidthDelta:75];
+
+#center a frame inside another frame
+CGRect centeredFrame = [FrameUtils frame:oldFrame centerInFrame:parentFrame];
+
+#print a frame to NSLog
+[FrameUtils printFrame:oldFrame];
+
+#"fix" a frame (set NAN dimensions to 0, and round all dimensions)
+CGRect fixedFrame = [FrameUtils fixFrame:oldFrame];
+
+If you're using these utilities often on UIView frame objects, consider using
+the UIVIew+FrameUtils category, more info is in UIView+FrameUtils.h. 
+
+Created by Jason Baker (jason@onejasonforsale.com) 
+& Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+
+The latest version of this code is available here:
+
+- https://bitbucket.org/tumbleon/tumbleon-utils
+
+This code is licensed under the Apache license, a non-viral open source license
+that lets you use this code freely within your own projects without requiring 
+your project itself to also be open source. More information about the Apache 
+license is here:
+
+- http://en.wikipedia.org/wiki/Apache_license
+
+Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer. 
+
+2. Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or other 
+materials provided with the distribution. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE. 
+
+The views and conclusions contained in the software and documentation are those of 
+the authors and should not be interpreted as representing official policies, either 
+expressed or implied.
+
+*/
+
+#import <Foundation/Foundation.h>
+
+@interface FrameUtils : NSObject
+
++ (CGRect) frame:(CGRect)frame resizeToSize:(CGSize)newSize;
++ (CGRect) frame:(CGRect)frame resizeToWidth:(CGFloat)width height:(CGFloat)height;
++ (CGRect) frame:(CGRect)frame resizeToWidth:(CGFloat)width;
++ (CGRect) frame:(CGRect)frame resizeToHeight:(CGFloat)height;
+
++ (CGRect) frame:(CGRect)frame resizeByDelta:(CGSize)delta;
++ (CGRect) frame:(CGRect)frame resizeByWidthDelta:(CGFloat)widthDelta heightDelta:(CGFloat)heightDelta;
++ (CGRect) frame:(CGRect)frame resizeByWidthDelta:(CGFloat)widthDelta;
++ (CGRect) frame:(CGRect)frame resizeByHeightDelta:(CGFloat)heightDelta;
+
++ (CGRect) frame:(CGRect)frame moveToPosition:(CGPoint)position;
++ (CGRect) frame:(CGRect)frame moveToX:(CGFloat)x y:(CGFloat)y;
++ (CGRect) frame:(CGRect)frame moveToX:(CGFloat)x;
++ (CGRect) frame:(CGRect)frame moveToY:(CGFloat)y;
+
++ (CGRect) frame:(CGRect)frame moveByDelta:(CGPoint)delta;
++ (CGRect) frame:(CGRect)frame moveByXDelta:(CGFloat)xDelta yDelta:(CGFloat)yDelta;
++ (CGRect) frame:(CGRect)frame moveByXDelta:(CGFloat)xDelta;
++ (CGRect) frame:(CGRect)frame moveByYDelta:(CGFloat)yDelta;
+
++ (CGRect) frame:(CGRect)frame centerInFrame:(CGRect)parentFrame;
++ (CGRect) frame:(CGRect)frame centerHorizontallyInFrame:(CGRect)parentFrame;
++ (CGRect) frame:(CGRect)frame centerVerticallyInFrame:(CGRect)parentFrame;
+
++ (CGFloat)fixFrameDim:(CGFloat)dim;
++ (CGRect) fixFrame:(CGRect)frame;
+
++ (CGRect) frameIpadLandscape;
++ (CGRect) frameIpadPortrait;
++ (CGRect) frameIPhoneLandscape;
++ (CGRect) frameIPhonePortrait;
+
++ (void) printFrame:(CGRect)frame label:(NSString *)label;
++ (void) printFrame:(CGRect)frame;
+
+@end

File Classes/FrameUtils.m

View file
+/*
+
+FrameUtils.m
+
+A collection of utilities that simplify common Objective C CGRect/Frame 
+operations such as resizing, moving, centering, debug logging, and more.
+
+Usage instructions/examples are provided in FrameUtils.h.
+
+Created by Jason Baker (jason@onejasonforsale.com) 
+& Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+
+The latest version of this code is available here:
+
+- https://bitbucket.org/tumbleon/tumbleon-utils
+
+This code is licensed under the Apache license, a non-viral open source license
+that lets you use this code freely within your own projects without requiring 
+your project itself to also be open source. More information about the Apache 
+license is here:
+
+- http://en.wikipedia.org/wiki/Apache_license
+
+Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer. 
+
+2. Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or other 
+materials provided with the distribution. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE. 
+
+The views and conclusions contained in the software and documentation are those of 
+the authors and should not be interpreted as representing official policies, either 
+expressed or implied.
+
+*/
+
+#import "FrameUtils.h"
+
+@implementation FrameUtils
+
++ (CGRect) frame:(CGRect)frame resizeToSize:(CGSize)newSize
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, newSize.width, newSize.height);
+}
+
++ (CGRect) frame:(CGRect)frame resizeToWidth:(CGFloat)width height:(CGFloat)height
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, width, height);
+}
+
++ (CGRect) frame:(CGRect)frame resizeToWidth:(CGFloat)width
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame resizeToHeight:(CGFloat)height
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, height);
+}
+
++ (CGRect) frame:(CGRect)frame resizeByDelta:(CGSize)delta
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width + delta.width, frame.size.height + delta.height);
+}
+
++ (CGRect) frame:(CGRect)frame resizeByWidthDelta:(CGFloat)widthDelta heightDelta:(CGFloat)heightDelta
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width + widthDelta, frame.size.height + heightDelta);
+}
+
++ (CGRect) frame:(CGRect)frame resizeByWidthDelta:(CGFloat)widthDelta
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width + widthDelta, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame resizeByHeightDelta:(CGFloat)heightDelta
+{
+    return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height + heightDelta);
+}
+
++ (CGRect) frame:(CGRect)frame moveToPosition:(CGPoint)position
+{
+    return CGRectMake(position.x, position.y, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame moveToX:(CGFloat)x y:(CGFloat)y
+{
+    return CGRectMake(x, y, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame moveToX:(CGFloat)x
+{
+    return CGRectMake(x, frame.origin.y, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame moveToY:(CGFloat)y
+{
+    return CGRectMake(frame.origin.x, y, frame.size.width, frame.size.height);
+}
+
+
++ (CGRect) frame:(CGRect)frame moveByDelta:(CGPoint)delta
+{
+    return CGRectMake(frame.origin.x + delta.x, frame.origin.y + delta.y, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame moveByXDelta:(CGFloat)xDelta yDelta:(CGFloat)yDelta
+{
+    return CGRectMake(frame.origin.x + xDelta, frame.origin.y + yDelta, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame moveByXDelta:(CGFloat)xDelta
+{
+    return CGRectMake(frame.origin.x + xDelta, frame.origin.y, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame moveByYDelta:(CGFloat)yDelta
+{
+    return CGRectMake(frame.origin.x, frame.origin.y + yDelta, frame.size.width, frame.size.height);
+}
+
++ (CGRect) frame:(CGRect)frame centerInFrame:(CGRect)parentFrame
+{
+    CGFloat x = parentFrame.origin.x + ((parentFrame.size.width - frame.size.width) / 2);
+    CGFloat y = parentFrame.origin.y + ((parentFrame.size.height - frame.size.height) / 2);
+    return [FrameUtils frame:frame moveToX:x y:y];
+}
+
++ (CGRect) frame:(CGRect)frame centerHorizontallyInFrame:(CGRect)parentFrame
+{
+    CGFloat x = parentFrame.origin.x + ((parentFrame.size.width - frame.size.width) / 2);
+    return [FrameUtils frame:frame moveToX:x];
+}
+
++ (CGRect) frame:(CGRect)frame centerVerticallyInFrame:(CGRect)parentFrame
+{
+    CGFloat y = parentFrame.origin.y + ((parentFrame.size.height - frame.size.height) / 2);
+    return [FrameUtils frame:frame moveToY:y];
+}
+
++ (CGFloat)fixFrameDim:(CGFloat)dim
+{
+    if (isnan(dim))
+    {
+        return 0.0f;
+    }
+    return round(dim);
+}
+
++ (CGRect) fixFrame:(CGRect)frame
+{
+    return CGRectMake([FrameUtils fixFrameDim:frame.origin.x], 
+                      [FrameUtils fixFrameDim:frame.origin.y], 
+                      [FrameUtils fixFrameDim:frame.size.width],
+                      [FrameUtils fixFrameDim:frame.size.height]);
+}
+
++ (CGRect) frameIpadLandscape
+{
+    return CGRectMake(0.0f, 0.0f, 1024.0f, 768.0f);
+}
+
++ (CGRect) frameIpadPortrait
+{
+    return CGRectMake(0.0f, 0.0f, 768.0f, 1024.0f);
+}
+
++ (CGRect) frameIPhoneLandscape
+{
+    return CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
+}
+
++ (CGRect) frameIPhonePortrait
+{
+    return CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
+}
+
++ (void) printFrame:(CGRect)frame label:(NSString *)label
+{
+    CGFloat ratio = frame.size.width / frame.size.height;
+    NSLog(@"Frame: %@, origin: %dx%d, size: %dx%d, ratio (w/h): %2.2f", ((label == nil) ? @"" : label), 
+          (int) frame.origin.x, (int) frame.origin.y, (int) frame.size.width, (int) frame.size.height, ratio);
+}
+
++ (void) printFrame:(CGRect)frame
+{
+    [FrameUtils printFrame:frame label:nil];
+}
+
+
+
+
+@end

File Classes/OperationManager.h

View file
+/*
+ 
+ OperationManager
+ 
+ A simple NSOperation manager, like NSOperationQueue, with some additional features.
+ 
+ ABOUT
+ 
+ OperationManager provides a simple interface to create a dynamic operation queue, with
+ a configurable maximum number of threads and queue thread priority. 
+ 
+ Threads are spun up as work is available, and die when all operations have been executed.
+ 
+ A number of methods are provided to simplify working with NSOperations in your own project,
+ with special emphesis placed on weak vs strong pointers to your target object.
+ 
+ Supports queuing NSOperations you create yourself, or can create them for you.
+ 
+ Supports block operations.
+ 
+ USAGE INSTRUCTIONS
+ 
+ See the OperationManagerExample.h and .m files for example usage.
+ 
+ Simply allocate an instance of OperationManager, and hang on to it:
+ 
+ self.opManager = [[OperationManager alloc] init];
+ 
+ Then queue up operations like so:
+ 
+ [self.opManager queueOperationWithWeakTarget:self 
+    selector:@selector(performAction:) object:@"myOperation4"];
+  
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OperationManager : NSObject
+// initialize an OperationManager with (device core count * 2) max thread count, and
+// DISPATCH_QUEUE_PRIORITY_BACKGROUND thread priority.
+- (id) init;
+
+// initialize an OperationManager with your own thread count and priority.
+- (id) initWithMaxThreads:(int)threadCount queueThreadPriority:(int)queueThreadPriority;
+
+// queue an operation you've created, this operation will be stored in a list
+// while queued, with a strong pointer keeping the instance around.
+- (void) queueOperation:(NSOperation*)operation;
+
+// queue an operation block
+- (NSOperation*) queueOperationBlock:(void (^)(void))block;
+
+// queue an operation with a weak pointer to your target, allowing your target to
+// dealloc safely before or while the operation executes
+- (NSOperation*) queueOperationWithWeakTarget:(id)target selector:(SEL)sel object:(id)arg;
+
+// queue an operation with a strong pointer to your target, forcing your target object
+// to stick around until the operation is dequeued and finishes execution
+- (NSOperation*) queueOperationWithStrongTarget:(id)target selector:(SEL)sel object:(id)arg;
+
+// remove the given operation from our internal operation queue
+- (void)removeOperation:(NSOperation*)op;
+
+// current count of operations in queue
+- (int) operationCount;
+
+//convenience method to determine device's core count (i.e. single core vs dual core)
++ (int) deviceCoreCount;
+
+@end

File Classes/OperationManager.m

View file
+/*
+ 
+ OperationManager
+ 
+ A simple NSOperation manager, like NSOperationQueue, with some additional features.
+ 
+ ABOUT
+ 
+ OperationManager provides a simple interface to create a dynamic operation queue, with
+ a configurable maximum number of threads and queue thread priority.
+ 
+ Threads are spun up as work is available, and die when all operations have been executed.
+ 
+ A number of methods are provided to simplify working with NSOperations in your own project,
+ with special emphesis placed on weak vs strong pointers to your target object.
+ 
+ Supports queuing NSOperations you create yourself, or can create them for you.
+ 
+ Supports block operations.
+ 
+ USAGE INSTRUCTIONS
+ 
+ See the OperationManagerExample.h and .m files for example usage.
+ 
+ Simply allocate an instance of OperationManager, and hang on to it:
+ 
+ self.opManager = [[OperationManager alloc] init];
+ 
+ Then queue up operations like so:
+ 
+ [self.opManager queueOperationWithWeakTarget:self
+ selector:@selector(performAction:) object:@"myOperation4"];
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "OperationManager.h"
+#import "DeviceConfig.h"
+#import "WeakWrapper.h"
+#include <mach/mach_host.h> //for countCores method
+
+@interface WeakNSInvocationOperation : NSObject
+@property (weak) id target;
+@property SEL   selector;
+@property (strong) id obj;
+- (void)start:(id)a;
+@end
+
+@implementation WeakNSInvocationOperation
+@synthesize target, selector,obj;
+
+- (void)start:(id)a {
+    if([target respondsToSelector:selector]) {
+        // hrm the warning for this is not good but as long as we don't call methods that return we should be ok
+        #pragma clang diagnostic push
+        #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+        [target performSelector:selector withObject:obj];
+        #pragma clang diagnostic pop
+    }
+}
+
+@end
+
+@interface OperationManager ()
+@property (strong) NSMutableArray * operationList;
+@property int maxThreads;
+@property int runningThreads;
+@property dispatch_queue_t myQueue;
+@end
+
+@implementation OperationManager
+
+@synthesize operationList, maxThreads, runningThreads, myQueue;
+
+- (id) initWithMaxThreads:(int)threadCount queueThreadPriority:(int)queueThreadPriority {
+    self = [super init];
+    if (self) {
+        self.maxThreads = threadCount;
+        self.runningThreads = 0;
+        self.operationList = [NSMutableArray array];
+        self.myQueue = dispatch_get_global_queue(queueThreadPriority, 0);
+    }
+    return self;
+}
+
+- (id) init {
+    self = [super init];
+    if (self) {
+        int threadCount = [OperationManager deviceCoreCount] * 2;
+        int queueThreadPriority = DISPATCH_QUEUE_PRIORITY_BACKGROUND;
+        self.maxThreads = threadCount;
+        self.runningThreads = 0;
+        self.operationList = [NSMutableArray array];
+        self.myQueue = dispatch_get_global_queue(queueThreadPriority, 0);
+    }
+    return self;
+}
+
+//source for this method: http://stackoverflow.com/questions/7241936/how-do-i-detect-a-dual-core-cpu-on-ios
+// thanks to the author: albertamg (http://stackoverflow.com/users/375300/albertamg)
++ (int) deviceCoreCount {
+    host_basic_info_data_t hostInfo;
+    mach_msg_type_number_t infoCount;    
+    infoCount = HOST_BASIC_INFO_COUNT;
+    host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);    
+    return (int)(hostInfo.max_cpus);
+}
+
+-(NSOperation*) queueOperationWithWeakTarget:(id)i selector:(SEL)s object:(id)obj {
+    WeakNSInvocationOperation * tar = [[WeakNSInvocationOperation alloc] init];
+    tar.target=i;
+    tar.selector=s;
+    tar.obj = obj;
+    NSInvocationOperation *op=[[NSInvocationOperation alloc] initWithTarget:tar selector:@selector(start:) object:nil];
+    [self queueOperation:op];
+    return op;
+}
+
+-(NSOperation*) queueOperationWithStrongTarget:(id)i selector:(SEL)s object:(id)obj {
+    NSInvocationOperation *op=[[NSInvocationOperation alloc] initWithTarget:i selector:s object:obj];
+    [self queueOperation:op];
+    return op;
+}
+
+
+- (NSOperation*) queueOperationBlock:(void (^)(void))block {
+    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:block];
+    [self queueOperation:op];
+    return op;
+}
+
+- (void) queueOperation:(NSOperation*)operation {
+    @synchronized (self.operationList) {
+        [self.operationList addObject:operation];
+    }
+    [self runLatest];
+}
+
+-(void) removeOperation:(NSOperation*)op {
+    @synchronized (self.operationList) {
+        [self.operationList removeObject:op];
+    }
+}
+
+- (int) operationCount {
+    @synchronized (self.operationList) {
+        return [self.operationList count];
+    }
+}
+
+
+- (void)runLatest {
+    dispatch_async(myQueue, ^{
+        // first check if there are already the max threads running:
+        @synchronized (self.operationList) {
+            if(self.runningThreads >= self.maxThreads)
+                return;
+            self.runningThreads++;
+        }
+        
+        // otherwise start a run loop:
+        while (YES) {
+            NSOperation *opParams=nil;
+            @synchronized (self.operationList) {
+                int index = [self.operationList count] - 1;
+                if(index<0)
+                {
+                    self.runningThreads--;
+                    return;
+                }
+                
+                opParams = (NSOperation*)[self.operationList objectAtIndex:index];
+                [self.operationList removeLastObject];
+            }
+            [opParams start];
+        }
+    });
+}
+
+@end

File Classes/OperationManagerExample.h

View file
+/*
+ 
+ OperationManagerExample
+ 
+ Example code illustrating OperationManager API usage.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OperationManagerExample : NSObject
+
+@end

File Classes/OperationManagerExample.m

View file
+/*
+ 
+ OperationManagerExample
+ 
+ Example code illustrating OperationManager API usage.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "OperationManagerExample.h"
+#import "OperationManager.h"
+
+@interface OperationManagerExample ()
+@property (strong) OperationManager * opManager;
+@property (strong) NSOperation * myOperation1;
+@property (strong) NSOperation * myOperation2;
+@end
+
+@implementation OperationManagerExample
+@synthesize opManager, myOperation1, myOperation2;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        //this will create an operation manager with a max thread count of (device core count * 2),
+        // and a queue thread priority of DISPATCH_QUEUE_PRIORITY_BACKGROUND
+        self.opManager = [[OperationManager alloc] init];
+        
+        //of course, we can dictate threadcount and queue thread priority too..
+        self.opManager = [[OperationManager alloc] initWithMaxThreads:4 queueThreadPriority:DISPATCH_QUEUE_PRIORITY_LOW];
+        
+        //the operation manager is a simple beast, it spins up threads on-demand (when there's something to work on), and
+        // kills them off when the queue is empty. the queue is fifo, a simple nsmutablearray.
+        
+        //in the case of executing a block operation, the block's strong or weak pointers to yourself
+        // are up to you, we'd recommend a weak pointer like this unless you really want your object's
+        // lifecycle to continue until the operation has executed..
+        
+        __weak OperationManagerExample * weakSelf = self;
+        [self.opManager queueOperationBlock:^{
+            [weakSelf performAction:@"block operation"];
+        }];
+        
+        //we could also make our own block operation and pass it in this way..
+        self.myOperation1 = [NSBlockOperation blockOperationWithBlock:^{
+            [weakSelf performAction:@"myOperation1"];
+        }];
+        [self.opManager queueOperation:self.myOperation1];
+        
+        //in the case of a normal NSOperation, the target object is held with a strong pointer
+        self.myOperation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performAction:) object:@"myOperation2"];
+        [self.opManager queueOperation:self.myOperation2];
+        
+        //operationManager has some other simplified methods to create an operation too..
+        //in the strong case, a strong pointer to your target is held by the operation until it is dequeued and executed.
+        NSOperation * myOperation3 = [self.opManager queueOperationWithStrongTarget:self selector:@selector(performAction:)
+                                                                             object:@"myOperation3"];
+        
+        //in the weak case, a weak pointer to your target is held by the operation, and if your object deallocs before
+        // operation execution, the operation becomes a no-op.
+        
+        [self.opManager queueOperationWithWeakTarget:self selector:@selector(performAction:) object:@"myOperation4"];
+        
+        //in both cases above, we don't have to save the operation if we don't want to, they're already strongly held by
+        // the operationmanager's operation list.
+        
+        //if we really care for some reason, we can cancel an operation, of course, again effectively turning it into
+        // a no-op when it's dequeued.. but remember that you can't gaurantee your cancel will happen before the operation's
+        // already going..
+        [myOperation3 cancel];
+        
+        //further, if for some reason you *really* want to ensure the operation's not in our operation list anymore, you can
+        // do the following, but again, you can't gaurantee you're dequeuing something that's not already executing..
+        [self.opManager removeOperation:myOperation3];        
+    }
+    return self;
+}
+
+- (void) performAction:(id)object {
+    NSLog(@"Now executing operation: %@", (NSString *) object);
+}
+
+@end

File Classes/PrimitiveWrappers.h

View file
+/*
+ 
+ PrimitiveWrappers
+ 
+ A collection of simple classes wrapping a mutable primitive value.
+ 
+ Sometimes you want to store mutable numbers in a collection such as
+ NSArray or NSDictionary, these classes make that possible.
+ 
+ If you want to store immutable numbers in a collection, use NSNumber.
+ 
+ Using one of the primitives is easy: 
+ 
+ IntWrapper * wrapper = [[IntWrapper alloc] init];
+ wrapper.value = 25;
+ 
+ NSMutableArray * array = [NSMutableArray array];
+ [array addObject:wrapper;
+ 
+ NSLog(@"value: %d", ((IntWrapper*)[array objectAtIndex:0]).value);
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface IntWrapper : NSObject
+@property int value;
+@end
+
+@interface LongWrapper : NSObject
+@property long value;
+@end
+
+@interface FloatWrapper : NSObject
+@property float value;
+@end
+
+@interface BoolWrapper : NSObject
+@property BOOL value;
+@end

File Classes/PrimitiveWrappers.m

View file
+/*
+ 
+ PrimitiveWrappers
+ 
+ A collection of simple classes wrapping a mutable primitive value.
+ 
+ Sometimes you want to store mutable numbers in a collection such as
+ NSArray or NSDictionary, these classes make that possible.
+ 
+ If you want to store immutable numbers in a collection, use NSNumber.
+ 
+ Using one of the primitives is easy:
+ 
+ IntWrapper * wrapper = [[IntWrapper alloc] init];
+ wrapper.value = 25;
+ 
+ NSMutableArray * array = [NSMutableArray array];
+ [array addObject:wrapper;
+ 
+ NSLog(@"value: %d", ((IntWrapper*)[array objectAtIndex:0]).value);
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "PrimitiveWrappers.h"
+
+@implementation IntWrapper
+@synthesize value;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        self.value = 0;
+    }
+    return self;
+}
+
+@end
+
+@implementation LongWrapper
+@synthesize value;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        self.value = 0;
+    }
+    return self;
+}
+
+@end
+
+@implementation FloatWrapper
+@synthesize value;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        self.value = 0;
+    }
+    return self;
+}
+
+@end
+
+@implementation BoolWrapper
+@synthesize value;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        self.value = false;
+    }
+    return self;
+}
+
+@end

File Classes/TableViewHelper.h

View file
+/*
+
+ TableViewHelper.h
+ 
+ A wrapper class to simplify UITableViewDelegate implementation. 
+
+ USAGE INSTRUCTIONS
+
+ See the TableViewHelperExample.h and .m files for example usage.
+ 
+ Using TableViewHelper is simpler than implementing the same-old
+ UITableViewDelegate methods and implementations over and over again.
+ 
+ TableViewHelper creates a single section table out of a NSMutableArray
+ data source that you provide. This wrapper is not the end-all/be-all 
+ wrapper that's perfect for every UITableView situation, but it works 
+ well in most simple cases.
+ 
+ You simply implement TableHelperDelegate methods in the class that will
+ own the TableViewHelper instance (usually the same class that owns the 
+ underlying UITableView), and wrap your TableViewHelper instance around
+ your UITableView. 
+ 
+ TableViewHelper will make itself your UITableView's delegate target, and 
+ delegate simplified operations to you, while managing some of the basic
+ operations like editable table items for you. 
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+*/
+#import <Foundation/Foundation.h>
+
+@protocol TableHelperDelegate <NSObject>
+@required
+/* Create and return a UITableViewCell instance for the given object from your data source. */
+- (UITableViewCell *) createCellForObject:(NSObject *)object;
+/* Perform an action based on the given selected object from your data source. */
+/* Provided cell object is the cell you've wrapped around the object. */
+- (void) objectSelected:(NSObject *)object cell:(UITableViewCell *)cell;
+@optional
+/* Optional method to perform an action when the given item is removed from your data source */
+- (void) objectDeleted:(NSObject *)object;
+@end
+
+@interface TableViewHelper : NSObject <UITableViewDataSource, UITableViewDelegate>
+
+@property (strong) UITableView * myTableView;
+@property (strong) NSMutableArray * dataSource;
+@property BOOL allowEdits;    
+@property (weak) id delegate;
+
++ (TableViewHelper *) createTableViewHelper:(UITableView *)tableView dataSource:(NSMutableArray *)dataSource delegate:(id)delegate;
+
+- (void) reload;
+
+@end

File Classes/TableViewHelper.m

View file
+/*
+ 
+ TableViewHelper.m
+ 
+ A wrapper class to simplify UITableViewDelegate implementation.
+ 
+ USAGE INSTRUCTIONS
+ 
+ See the TableViewHelperExample.h and .m files for example usage.
+ 
+ Using TableViewHelper is simpler than implementing the same-old
+ UITableViewDelegate methods and implementations over and over again.
+ 
+ TableViewHelper creates a single section table out of a NSMutableArray
+ data source that you provide. This wrapper is not the end-all/be-all
+ wrapper that's perfect for every UITableView situation, but it works
+ well in most simple cases.
+ 
+ You simply implement TableHelperDelegate methods in the class that will
+ own the TableViewHelper instance (usually the same class that owns the
+ underlying UITableView), and wrap your TableViewHelper instance around
+ your UITableView.
+ 
+ TableViewHelper will make itself your UITableView's delegate target, and
+ delegate simplified operations to you, while managing some of the basic
+ operations like editable table items for you.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "TableViewHelper.h"
+
+@implementation TableViewHelper
+
+@synthesize myTableView, dataSource, allowEdits, delegate;
+
++ (TableViewHelper *) createTableViewHelper:(UITableView *)tableView dataSource:(NSMutableArray *)dataSource delegate:(id)delegate {
+    TableViewHelper * tvh = [[TableViewHelper alloc] init];
+    tvh.myTableView = tableView;
+    tvh.allowEdits = YES;
+    tvh.dataSource = dataSource;
+    tvh.delegate = delegate;
+    tableView.delegate = tvh;
+    tableView.dataSource = tvh;
+    return tvh;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+    return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return [self.dataSource count];
+}
+
+// Override to support conditional editing of the table view.
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
+    // Return NO if you do not want the specified item to be editable.
+    return self.allowEdits;
+}
+
+// Override to support editing the table view.
+- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (editingStyle == UITableViewCellEditingStyleDelete) {
+        // Delete the row from the data source
+        NSObject * object = [self.dataSource objectAtIndex:indexPath.row];
+		[self.dataSource removeObjectAtIndex:indexPath.row];
+        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
+        if ([self.delegate respondsToSelector:@selector(objectDeleted:)]) {
+            [self.delegate objectDeleted:object];
+        }
+    }
+    else if (editingStyle == UITableViewCellEditingStyleInsert) {
+        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
+        NSLog(@"ERROR: TableViewHelper doesnt support UITableViewCellEditingStyleInsert");
+    }   
+}
+
+// Override to support rearranging the table view.
+- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath  {
+    NSObject * item = [self.dataSource objectAtIndex:fromIndexPath.row];
+    [self.dataSource removeObjectAtIndex:fromIndexPath.row];
+    [self.dataSource insertObject:item atIndex:toIndexPath.row];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    NSObject * object = [self.dataSource objectAtIndex:indexPath.row];
+    UITableViewCell * cell = [self.myTableView cellForRowAtIndexPath:indexPath];
+    [self.delegate objectSelected:object cell:cell];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    NSObject * object = [self.dataSource objectAtIndex:indexPath.row];
+    return [delegate createCellForObject:object];
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];    return cell.frame.size.height;    
+}
+
+- (void) reload {
+    self.myTableView.delegate = self;
+    self.myTableView.dataSource = self;
+    [self.myTableView reloadData];
+}
+
+@end

File Classes/TableViewHelperExample.h

View file
+/*
+ 
+ TableViewHelperExample.h
+ 
+ An example implementation demonstrating the benefits of TableViewHelper.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "TableViewHelper.h" //this defines the TableHelperDelegate protocol
+
+//Your parent class that owns the TableViewHelper (and likely the underlying UITableView) needs
+// to implement TableHelperDelegate instead of UITableViewDelegate, like so:
+@interface TableViewHelperExample : UIViewController <TableHelperDelegate, UIAlertViewDelegate>
+
+//our underlying tableview, note that the tableviewhelper also holds onto this
+// with a strong pointer
+@property (strong) UITableView * tableView;
+
+//our tableviewhelper instance, we are responsible for holding onto this
+@property (strong) TableViewHelper * tableViewHelper;
+
+//our datasource we'll use with our tableview and tableviewhelper
+@property (strong) NSMutableArray * dataSource;
+@end

File Classes/TableViewHelperExample.m

View file
+/*
+ 
+ TableViewHelperExample.m
+ 
+ An example implementation demonstrating the benefits of TableViewHelper.
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "TableViewHelperExample.h"
+
+@interface TableViewHelperExample ()
+
+@end
+
+@implementation TableViewHelperExample
+
+@synthesize tableView, tableViewHelper, dataSource;
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+	
+    //first, we create our data source
+    self.dataSource = [NSMutableArray array];
+    [self.dataSource addObject:@"Adam"];
+    [self.dataSource addObject:@"Amanda"];
+    [self.dataSource addObject:@"Jason"];
+    
+    //next, create the tableview..
+    self.tableView = [[UITableView alloc] initWithFrame:
+                      CGRectMake(0,0,self.view.frame.size.width,
+                                 self.view.frame.size.height)];
+    [self.view addSubview:self.tableView];
+    
+    //now setup our tableviewhelper
+    self.tableViewHelper = [TableViewHelper createTableViewHelper:self.tableView
+                                                       dataSource:self.dataSource
+                                                         delegate:self];
+    
+    //by default, tableviewhelper allows edits, to turn that off we do this:
+    self.tableViewHelper.allowEdits = NO;
+    
+    //if the tableviewhelper allows edits, moving items in the list will be automatically
+    // handled by the tableviewhelper, as will deletes
+    
+    //when a delete happens, our delegate method objectDeleted will be called, in case
+    // we want to save state or something..
+    
+    //note that tableviewhelper is intended for very simple use cases, and thus hard codes
+    // the section count for this table to 1.
+}
+
+- (void) addAction {
+    //if we wanted to add an object to our data source and reload the table
+    // we'd simply do this..
+    [self.dataSource addObject:@"TumbleOn"];
+    [self.tableView reloadData];
+}
+
+- (void) startEditAction {
+    //to enable edits we'd do this.. and that's it, no UITableViewDelegate methods to worry
+    // about b/c tableviewhelper automatically handles that for us
+    [self.tableView setEditing:YES animated:YES];
+}
+
+- (void) endEditAction {
+    //disabling edits..
+    // now would be a good time to save state
+    [self.tableView setEditing:NO animated:YES];
+}
+
+/* Create and return a UITableViewCell instance for the given object from your data source. */
+- (UITableViewCell *) createCellForObject:(NSObject *)object {
+    // this is essentially UITableViewDelegate's cellForRowAtIndexPath impl
+    NSLog(@"Creating cell for object: %@", (NSString*)object);
+    NSString * cellIdentifier = @"someIdentifier";
+    UITableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
+    if (cell == nil) {
+        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
+    }
+    cell.textLabel.text = (NSString*)object;
+    return cell;
+}
+
+/* Perform an action based on the given selected object from your data source. */
+/* Provided cell object is the cell you've wrapped around the object. */
+- (void) objectSelected:(NSObject *)object cell:(UITableViewCell *)cell {
+    NSLog(@"Object selected: %@", (NSString*)object);
+}
+
+/* Optional method to perform an action when the given item is removed from your data source */
+- (void) objectDeleted:(NSObject *)object {
+    NSLog(@"Object deleted: %@", (NSString*)object);
+}
+
+
+@end

File Classes/TouchDelegatorView.h

View file
+/*
+ 
+ TouchDelegatorView
+ 
+ UIView that delegates all touch events (and long press gestures) to a delegate.
+ 
+ USAGE INSTRUCTIONS
+ 
+ We often use TouchDelegatorView in our apps to easily capture and forward a
+ touch event (and/or long press gesture) simply. Example usages include overlaying
+ our image stream images in TumbleOn with this view to grab the long press, or creating
+ a full-screen transparent view below a popup view, to redirect touches to a close-popup
+ event elsewhere.
+ 
+
+ Simply create your TouchDelegatorView, and set its delegate to the class that should
+ receive the touch events:
+ 
+ - (void) viewDidLoad {
+   [super viewDidLoad];
+   TouchDelegatorView * delegator = [[TouchDelegatorView alloc] initWithFrame:CGRectMake(0,0,100,100)];
+   delegator.delegate = self;
+   [self.view addSubView:delegator];
+ }
+ 
+ - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+   NSLog(@"Received touches ended event..");
+ }
+ 
+ - (void) longPress:(id)sender {
+   NSLog(@"long press..");
+ }
+ 
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface TouchDelegatorView : UIView
+
+@property (weak) UIResponder * delegate;
+@end

File Classes/TouchDelegatorView.m

View file
+/*
+ 
+ TouchDelegatorView
+ 
+ UIView that delegates all touch events (and long press gestures) to a delegate.
+ 
+ USAGE INSTRUCTIONS
+ 
+ We often use TouchDelegatorView in our apps to easily capture and forward a
+ touch event (and/or long press gesture) simply. Example usages include overlaying
+ our image stream images in TumbleOn with this view to grab the long press, or creating
+ a full-screen transparent view below a popup view, to redirect touches to a close-popup
+ event elsewhere.
+ 
+ 
+ Simply create your TouchDelegatorView, and set its delegate to the class that should
+ receive the touch events:
+ 
+ - (void) viewDidLoad {
+ [super viewDidLoad];
+ TouchDelegatorView * delegator = [[TouchDelegatorView alloc] initWithFrame:CGRectMake(0,0,100,100)];
+ delegator.delegate = self;
+ [self.view addSubView:delegator];
+ }
+ 
+ - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+ NSLog(@"Received touches ended event..");
+ }
+ 
+ - (void) longPress:(id)sender {
+ NSLog(@"long press..");
+ }
+ 
+ 
+ ---
+ 
+ Created by Jason Baker (jason@onejasonforsale.com)
+ & Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+ 
+ The latest version of this code is available here:
+ 
+ - https://bitbucket.org/tumbleon/tumbleon-utils
+ 
+ This code is licensed under the Apache license, a non-viral open source license
+ that lets you use this code freely within your own projects without requiring
+ your project itself to also be open source. More information about the Apache
+ license is here:
+ 
+ - http://en.wikipedia.org/wiki/Apache_license
+ 
+ Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+ 
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ 
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ The views and conclusions contained in the software and documentation are those of
+ the authors and should not be interpreted as representing official policies, either
+ expressed or implied.
+ 
+ */
+
+#import "TouchDelegatorView.h"
+
+@implementation TouchDelegatorView
+
+@synthesize delegate;
+
+- (id)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.userInteractionEnabled = YES;
+        UILongPressGestureRecognizer * longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
+        longPressGesture.minimumPressDuration = 0.5f;
+		[self addGestureRecognizer:longPressGesture];
+    }
+    return self;
+}
+
+- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+    if ([self.delegate respondsToSelector:@selector(touchesBegan:withEvent:)]) {
+        [self.delegate touchesBegan:touches withEvent:event];
+    }
+    [super touchesBegan:touches withEvent:event];
+}
+
+- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+    if ([self.delegate respondsToSelector:@selector(touchesCancelled:withEvent:)]) {
+        [self.delegate touchesCancelled:touches withEvent:event];
+    }
+    [super touchesCancelled:touches withEvent:event];    
+}
+
+- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+    if ([self.delegate respondsToSelector:@selector(touchesEnded:withEvent:)]) {
+        [self.delegate touchesEnded:touches withEvent:event];
+    }
+    [super touchesEnded:touches withEvent:event];    
+}
+
+- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+    if ([self.delegate respondsToSelector:@selector(touchesMoved:withEvent:)]) {
+        [self.delegate touchesMoved:touches withEvent:event];
+    }
+    [super touchesMoved:touches withEvent:event];    
+}
+
+- (void)longPress:(UILongPressGestureRecognizer *)gesture {
+	// only when gesture was recognized, not when ended
+	if (gesture.state == UIGestureRecognizerStateBegan) {
+		if ([self.delegate respondsToSelector:@selector(longPress:)]) {
+            [self.delegate performSelector:@selector(longPress:) withObject:nil];
+        }
+	}
+}
+
+@end

File Classes/UIView+FrameUtils.h

View file
+/*
+
+UIView+FrameUtils.h
+
+This is a category on UIView that adds convenience methods that utilize
+FrameUtils operations to resize, move, center, debug log and more for 
+a given UIView's frame. 
+
+USAGE INSTRUCTIONS
+
+Using this category is simple. Simply include the source code from the
+FrameUtils.zip file in your Objective C project, then import this file in
+any file where you would like to use the methods provided by this category.
+
+USAGE EXAMPLES
+
+#move a UIView's frame to position 0,0
+[view frameMoveToX:0 y:0];
+
+#move a UIView's frame left by 50 pixels
+[view frameMoveByXDelta:-50];
+
+#resize a UIView's frame to 50x100
+[view frameResizeToWidth:50 height:100];
+
+#resize a UIView's frame to be 75 pixels wider
+[view frameResizeByWidthDelta:75];
+
+#center a UIView's frame inside another view's frame
+[view frameCenterInFrame:otherView.frame];
+
+#print a UIView's frame to NSLog
+[view framePrint];
+
+#"fix" a UIView's frame (set NAN dimensions to 0, and round all dimensions)
+[view frameFix];
+
+Additional utility methods are provided in FrameUtils.  
+
+For more information about Objective-C Categories, visit these resources:
+
+- http://en.wikipedia.org/wiki/Objective-C#Categories
+
+- http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html
+
+Created by Jason Baker (jason@onejasonforsale.com) 
+& Adam Zacharski (zacharski@gmail.com) for TumbleOn, March 2012.
+
+The latest version of this code is available here:
+
+- https://bitbucket.org/tumbleon/tumbleon-utils
+
+This code is licensed under the Apache license, a non-viral open source license
+that lets you use this code freely within your own projects without requiring 
+your project itself to also be open source. More information about the Apache 
+license is here:
+
+- http://en.wikipedia.org/wiki/Apache_license
+
+Copyright (c) 2012, Pocket Sized Giraffe, LLC. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer. 
+
+2. Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or other 
+materials provided with the distribution.