Commits

Kunal Parmar committed 1339862

Adding Xcode project with a framework target.

* Adding the gitignore file.
* Adding an NSObject category with
a. macro for compile time verification of key-value properties,
b. safer mechanism for canceling and rescheduling a selector to be called
after a delay.

Comments (0)

Files changed (10)

+.DS_Store
+
+# xcode noise
+build
+project.xcworkspace
+xcuserdata

KPT.xcodeproj/project.pbxproj

+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		E73BBF4E154B668200A3FA0D /* KPTNSObject+Foundation.h in Headers */ = {isa = PBXBuildFile; fileRef = E73BBF4C154B668200A3FA0D /* KPTNSObject+Foundation.h */; };
+		E73BBF4F154B668200A3FA0D /* KPTNSObject+Foundation.m in Sources */ = {isa = PBXBuildFile; fileRef = E73BBF4D154B668200A3FA0D /* KPTNSObject+Foundation.m */; };
+		E794A568154B5BA60013843F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7B87D79154B50A5000E3E0A /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		E73BBF4C154B668200A3FA0D /* KPTNSObject+Foundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KPTNSObject+Foundation.h"; sourceTree = "<group>"; };
+		E73BBF4D154B668200A3FA0D /* KPTNSObject+Foundation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "KPTNSObject+Foundation.m"; sourceTree = "<group>"; };
+		E794A52A154B562F0013843F /* KPTShared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = KPTShared.xcconfig; sourceTree = "<group>"; };
+		E794A52C154B57CA0013843F /* KPTSharedDebug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = KPTSharedDebug.xcconfig; sourceTree = "<group>"; };
+		E794A52D154B58050013843F /* KPTSharedRelease.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = KPTSharedRelease.xcconfig; sourceTree = "<group>"; };
+		E794A567154B5BA60013843F /* KPT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KPT.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		E794A58D154B5BCC0013843F /* KPTFramework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = KPTFramework.xcconfig; sourceTree = "<group>"; };
+		E794A590154B5C7F0013843F /* KPTFramework-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KPTFramework-Info.plist"; sourceTree = "<group>"; };
+		E794A593154B5C930013843F /* KPTFramework-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KPTFramework-Prefix.pch"; sourceTree = "<group>"; };
+		E7B87D79154B50A5000E3E0A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+		E7B87D7C154B50A5000E3E0A /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+		E7B87D7D154B50A5000E3E0A /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
+		E7B87D7E154B50A5000E3E0A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		E7B87D8F154B50A5000E3E0A /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		E794A563154B5BA60013843F /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E794A568154B5BA60013843F /* Cocoa.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		E73BBF44154B644200A3FA0D /* Sources */ = {
+			isa = PBXGroup;
+			children = (
+				E73BBF4C154B668200A3FA0D /* KPTNSObject+Foundation.h */,
+				E73BBF4D154B668200A3FA0D /* KPTNSObject+Foundation.m */,
+			);
+			path = Sources;
+			sourceTree = SOURCE_ROOT;
+		};
+		E794A51D154B51BA0013843F /* Other */ = {
+			isa = PBXGroup;
+			children = (
+				E794A51E154B51BA0013843F /* Config */,
+				E794A521154B51BA0013843F /* Plist */,
+				E794A522154B51BA0013843F /* Prefix */,
+			);
+			path = Other;
+			sourceTree = SOURCE_ROOT;
+		};
+		E794A51E154B51BA0013843F /* Config */ = {
+			isa = PBXGroup;
+			children = (
+				E794A51F154B51BA0013843F /* Project */,
+				E794A520154B51BA0013843F /* Target */,
+			);
+			path = Config;
+			sourceTree = "<group>";
+		};
+		E794A51F154B51BA0013843F /* Project */ = {
+			isa = PBXGroup;
+			children = (
+				E794A52A154B562F0013843F /* KPTShared.xcconfig */,
+				E794A52C154B57CA0013843F /* KPTSharedDebug.xcconfig */,
+				E794A52D154B58050013843F /* KPTSharedRelease.xcconfig */,
+			);
+			path = Project;
+			sourceTree = "<group>";
+		};
+		E794A520154B51BA0013843F /* Target */ = {
+			isa = PBXGroup;
+			children = (
+				E794A58D154B5BCC0013843F /* KPTFramework.xcconfig */,
+			);
+			path = Target;
+			sourceTree = "<group>";
+		};
+		E794A521154B51BA0013843F /* Plist */ = {
+			isa = PBXGroup;
+			children = (
+				E794A590154B5C7F0013843F /* KPTFramework-Info.plist */,
+			);
+			path = Plist;
+			sourceTree = "<group>";
+		};
+		E794A522154B51BA0013843F /* Prefix */ = {
+			isa = PBXGroup;
+			children = (
+				E794A593154B5C930013843F /* KPTFramework-Prefix.pch */,
+			);
+			path = Prefix;
+			sourceTree = "<group>";
+		};
+		E7B87D6A154B50A5000E3E0A = {
+			isa = PBXGroup;
+			children = (
+				E73BBF44154B644200A3FA0D /* Sources */,
+				E794A51D154B51BA0013843F /* Other */,
+				E7B87D78154B50A5000E3E0A /* Frameworks */,
+				E7B87D77154B50A5000E3E0A /* Products */,
+			);
+			indentWidth = 2;
+			sourceTree = "<group>";
+			tabWidth = 2;
+		};
+		E7B87D77154B50A5000E3E0A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				E794A567154B5BA60013843F /* KPT.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		E7B87D78154B50A5000E3E0A /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				E7B87D7C154B50A5000E3E0A /* AppKit.framework */,
+				E7B87D79154B50A5000E3E0A /* Cocoa.framework */,
+				E7B87D7D154B50A5000E3E0A /* CoreData.framework */,
+				E7B87D7E154B50A5000E3E0A /* Foundation.framework */,
+				E7B87D8F154B50A5000E3E0A /* SenTestingKit.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		E794A564154B5BA60013843F /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E73BBF4E154B668200A3FA0D /* KPTNSObject+Foundation.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		E794A566154B5BA60013843F /* KPTFramework */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = E794A587154B5BA60013843F /* Build configuration list for PBXNativeTarget "KPTFramework" */;
+			buildPhases = (
+				E794A562154B5BA60013843F /* Sources */,
+				E794A563154B5BA60013843F /* Frameworks */,
+				E794A564154B5BA60013843F /* Headers */,
+				E794A565154B5BA60013843F /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = KPTFramework;
+			productName = KPTFramework;
+			productReference = E794A567154B5BA60013843F /* KPT.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		E7B87D6C154B50A5000E3E0A /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0420;
+				ORGANIZATIONNAME = Box;
+			};
+			buildConfigurationList = E7B87D6F154B50A5000E3E0A /* Build configuration list for PBXProject "KPT" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = E7B87D6A154B50A5000E3E0A;
+			productRefGroup = E7B87D77154B50A5000E3E0A /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				E794A566154B5BA60013843F /* KPTFramework */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		E794A565154B5BA60013843F /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		E794A562154B5BA60013843F /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E73BBF4F154B668200A3FA0D /* KPTNSObject+Foundation.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		E794A588154B5BA60013843F /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = E794A58D154B5BCC0013843F /* KPTFramework.xcconfig */;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		E794A589154B5BA60013843F /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = E794A58D154B5BCC0013843F /* KPTFramework.xcconfig */;
+			buildSettings = {
+			};
+			name = Release;
+		};
+		E7B87D9E154B50A5000E3E0A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = E794A52C154B57CA0013843F /* KPTSharedDebug.xcconfig */;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		E7B87D9F154B50A5000E3E0A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = E794A52D154B58050013843F /* KPTSharedRelease.xcconfig */;
+			buildSettings = {
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		E794A587154B5BA60013843F /* Build configuration list for PBXNativeTarget "KPTFramework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				E794A588154B5BA60013843F /* Debug */,
+				E794A589154B5BA60013843F /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		E7B87D6F154B50A5000E3E0A /* Build configuration list for PBXProject "KPT" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				E7B87D9E154B50A5000E3E0A /* Debug */,
+				E7B87D9F154B50A5000E3E0A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = E7B87D6C154B50A5000E3E0A /* Project object */;
+}

Other/Config/Project/KPTShared.xcconfig

+//
+//  KPTSharedRelease.xcconfig
+//
+//  Xcode configuration file for building a Release configuration.
+//
+//  Created by Kunal Parmar on 4/27/12.
+//  Copyright (c) 2012 Kunal Parmar. All rights reserved.
+//
+
+// Architectures for which the product will be built.
+ARCHS = $(ARCHS_STANDARD_32_64_BIT)
+
+// The base SDK being used during the build.
+SDKROOT = macosx10.6
+
+// Build only the active architecture.
+ONLY_ACTIVE_ARCH = YES
+
+// Compiler for C, C++ and ObjC.
+GCC_VERSION = com.apple.compilers.llvm.clang.1_0
+
+// Minimum OS X version required.
+MACOSX_DEPLOYMENT_TARGET = 10.6
+
+// #include <string.h> should not search user paths.
+ALWAYS_SEARCH_USER_PATHS = NO
+
+// Generates a precompiled header for the prefix header which reduces overall build times.
+GCC_PRECOMPILE_PREFIX_HEADER = YES
+
+// Warn if a value is implicity converted from 64-bit type to a 32-bit type.
+GCC_WARN_64_TO_32_BIT_CONVERSION = YES
+
+// Warn if an aggregrate or union initializer is not fully bracketed.
+GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
+
+// Warn on no or mismatched return type.
+GCC_WARN_ABOUT_RETURN_TYPE = YES
+
+// Warn about missing prototypes.
+GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
+
+// Warn when a source file does not end with a newline.
+GCC_WARN_ABOUT_MISSING_NEWLINE = YES
+
+// Warn when a comparison between signed and unsigned values could produce incorrect result.
+GCC_WARN_SIGN_COMPARE = YES
+
+// Treat all warnings as errors.
+GCC_TREAT_WARNINGS_AS_ERRORS = YES
+
+// Warn on a @selector expression referring to an undeclared selector.
+GCC_WARN_UNDECLARED_SELECTOR = YES
+
+// Warn on unused functions.
+GCC_WARN_UNUSED_FUNCTION = YES
+
+// Warn on unused labels.
+GCC_WARN_UNUSED_LABEL = YES
+
+// Warn on unused parameters.
+GCC_WARN_UNUSED_PARAMETER = YES
+
+// Warn on unused variables.
+GCC_WARN_UNUSED_VARIABLE = YES

Other/Config/Project/KPTSharedDebug.xcconfig

+//
+//  KPTSharedDebug.xcconfig
+//
+//  Xcode configuration file for building a Debug configuration.
+//
+//  Created by Kunal Parmar on 4/27/12.
+//  Copyright (c) 2012 Kunal Parmar. All rights reserved.
+//
+
+#include "KPTShared.xcconfig"
+
+// No optimization.
+GCC_OPTIMIZATION_LEVEL = 0
+
+// Preprocessor macros.
+GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited)
+
+// Debugging information format.
+DEBUG_INFORMATION_FORMAT = dwarf

Other/Config/Project/KPTSharedRelease.xcconfig

+//
+// Brief    Shared project configuration for Release builds.
+//
+// Author   Kunal Parmar (kunalparmar@gmail.com)
+//
+// Copyright 2012 Kunal Parmar. All rights reserved.
+//
+
+#include "KPTShared.xcconfig"
+
+// Optimize for space and size.
+GCC_OPTIMIZATION_LEVEL = s
+
+// Debugging information format.
+DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
+
+// Strip binaries and set file mode, owner and group information to standard values.
+DEPLOYMENT_POSTPROCESSING = YES

Other/Config/Target/KPTFramework.xcconfig

+//
+//  KPTFramework.xcconfig
+//
+//  Xcode configuration file for KPTFramework target.
+//
+//  Created by Kunal Parmar on 4/27/12.
+//  Copyright (c) 2012 Kunal Parmar. All rights reserved.
+//
+
+PRODUCT_NAME = KPT
+
+// Strips non-global symbols, but saves external symbols.
+STRIP_STYLE = non-global
+
+// Bundles need to be position independent.
+GCC_DYNAMIC_NO_PIC = NO
+
+// Prefix header file.
+GCC_PREFIX_HEADER = Other/Prefix/KPTFramework-Prefix.pch

Other/Plist/KPTFramework-Info.plist

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.kunalparmar.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2012 Kunal Parmar. All rights reserved.</string>
+</dict>
+</plist>

Other/Prefix/KPTFramework-Prefix.pch

+//
+//  KPTFramework.xcconfig
+//
+//  Prefix header file for all source files of KPTFramework target.
+//
+//  Created by Kunal Parmar on 4/27/12.
+//  Copyright (c) 2012 Kunal Parmar. All rights reserved.
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif

Sources/KPTNSObject+Foundation.h

+//
+//  KPTNSObject+Foundation.h
+//
+//  Created by Kunal Parmar on 4/27/12.
+//  Copyright (c) 2012 Kunal Parmar. All rights reserved.
+//
+
+// A macro for compile time checks to make sure the property being accessed
+// using key-value coding is implemented by a class.
+//
+// Discussion
+//  -[NSObject valueForKey:] raises an exception when it does not find a
+//  property corresponding to a given key. This happens at runtime and will most
+//  probably cause the program to crash. This macros avoids these runtime
+//  crashes by checking at compile time whether a given class has a property for
+//  a given key.
+//
+//  Example, -[MyArray valueForKey:@"name"] would be replaced by
+//  -[MyArray valueForKey:NSStringForKey(name, MyClass)].
+//
+//  To ensure that performance is not affected, this macro is a no-op in
+//  non-Debug builds.
+#ifdef DEBUG
+  #define NSStringForKey(key, class) ([(class *)nil key], @#key)
+#else
+  #define NSStringForKey(key, class) @#key
+#endif // DEBUG
+
+@interface NSObject (KPTNSObjectFoundation)
+
+// Safer way of doing +cancelPreviousPerformRequestsWithTarget:selector:object:
+// followed by -performSelector:withObject:afterDelay:.
+//
+// Dicussion
+//  -performSelector:withObject:afterDelay: retains self and the argument passed
+//  to it. If you directly call
+//  +cancelPreviousPerformRequestsWithTarget:selector:object:, it will release
+//  self and the argument which may cause them to be deallocated. Using those
+//  objects further might cause a crash.
+//
+//  This method retains self and the argument before calling
+//  +cancelPreviousPerformRequestsWithTarget:selector:object:, which ensures
+//  that the objects will not get deallocated, then calls
+//  -performSelector:withObject:afterDelay: and then releases self and the
+//  argument.
+- (void)kpt_coalescedPerformSelector:(SEL)aSelector
+                          withObject:(id)anArgument
+                          afterDelay:(NSTimeInterval)delay;
+
+@end

Sources/KPTNSObject+Foundation.m

+//
+//  KPTNSObject+Foundation.m
+//
+//  Created by Kunal Parmar on 4/27/12.
+//  Copyright (c) 2012 Kunal Parmar. All rights reserved.
+//
+
+#import "KPTNSObject+Foundation.h"
+
+@implementation NSObject (KPTNSObjectFoundation)
+
+- (void)kpt_coalescedPerformSelector:(SEL)aSelector
+                          withObject:(id)anArgument
+                          afterDelay:(NSTimeInterval)delay
+{
+  [self retain];
+  [anArgument retain];
+  [[self class] cancelPreviousPerformRequestsWithTarget:self
+                                               selector:aSelector
+                                                 object:anArgument];
+  [self performSelector:aSelector
+             withObject:anArgument
+             afterDelay:delay];
+  [anArgument release];
+  [self release];
+}
+
+@end