Skip to content

Instantly share code, notes, and snippets.

@fxfactorial
Created July 21, 2017 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fxfactorial/5c2455f697523dc35e886f6b38ce8554 to your computer and use it in GitHub Desktop.
Save fxfactorial/5c2455f697523dc35e886f6b38ce8554 to your computer and use it in GitHub Desktop.
Stack objects in Objective-C
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface SomeClass : NSObject
@property (nonatomic, assign) NSInteger someDefaultNumber;
@property (nonatomic, assign) NSInteger someCustomNumber;
- (void)method;
@end
@implementation SomeClass
- (instancetype)init
{
self = [super init];
if (self == nil) {
return self;
}
_someDefaultNumber = 100;
return self;
}
- (void)method
{
NSLog(@"SomeClass: method");
}
- (void)someOtherMethod
{
NSLog(@"SomeClass: someOtherMethod");
}
- (void)dealloc
{
NSLog(@"SomeClass: dealloc");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Create objects on stack
// Important to notice that stack values don't participate in normal allocation / deallocation
// therefore they have to be passed to a block or another function because it's not possible to return pointers
// to local stack values
// Setup some
static size_t classSize;
static Class fakeClass;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
fakeClass = [SomeClass class];
classSize = class_getInstanceSize(fakeClass);
});
void(^work)(SomeClass *) = ^void(SomeClass *someClass) {
[someClass method];
NSCAssert(someClass.someDefaultNumber == 100, @"Something is wrong");
NSCAssert(someClass.someCustomNumber == 200, @"Something is wrong");
};
// Create heap object the "normal" way
//SomeClass *stackObject2 = [[SomeClass alloc] init];
// Create stack object 1 - non ARC as objc_constructInstance is not available
// uint8_t buffer[size];
// SomeClass *stackObject1 = objc_constructInstance(fakeClass, buffer); // Does not exist in ARC
// stackObject1.someCustomNumber = 200;
// work(stackObject1);
// [someClass release]; // not be abled to call release, because stack values don't participate in normal allocation / deallocation
// Create stack object 2 - ARC
void *stackObject2Mem = alloca(classSize);
memset(stackObject2Mem, 0, classSize);
object_setClass(((__bridge id)stackObject2Mem), [SomeClass class]);
SomeClass *stackObject2 = (__bridge SomeClass *)stackObject2Mem;
__unused id _ = [stackObject2 init];
stackObject2.someCustomNumber = 200;
// have to pass 'obj' to a block or another function because we can't return pointers to local stack values
// no release of 'key' because stack values don't participate in normal allocation / deallocation
work(stackObject2);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment