Last active
April 21, 2024 15:56
-
-
Save pookjw/ee503a3396ccd106866cb6a9453e79ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import <objc/runtime.h> | |
@interface MyObject : NSObject <NSCopying> { | |
@package NSUInteger _first; | |
@package NSInteger _second; | |
@package BOOL _third; | |
} | |
@end | |
@implementation MyObject | |
- (nonnull id)copyWithZone:(nullable NSZone *)zone { | |
id copy = [[self class] new]; | |
if (copy) { | |
unsigned int ivarsCount; | |
Ivar *ivars = class_copyIvarList([MyObject class], &ivarsCount); | |
ptrdiff_t minOffset = ivar_getOffset(ivars[0]); | |
ptrdiff_t maxOffset = ivar_getOffset(ivars[ivarsCount - 1]); | |
// https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-runtime-new.h#L236 | |
uint32_t lastIvarSize = *(uint32_t *)((uintptr_t)ivars[ivarsCount - 1] + sizeof(int32_t *) + sizeof(const char *) + sizeof(const char *) + sizeof(uint32_t)); | |
free(ivars); | |
const void *src = (const void *)((uintptr_t)self + minOffset); | |
void *dst = (void *)((uintptr_t)copy + minOffset); | |
memcpy(dst, src, maxOffset - minOffset + lastIvarSize); | |
} | |
return copy; | |
} | |
@end | |
int main(int argc, const char * argv[]) { | |
@autoreleasepool { | |
MyObject *myObject_1 = [MyObject new]; | |
myObject_1->_first = 3; | |
myObject_1->_second = 2; | |
myObject_1->_third = YES; | |
MyObject *myObject_2 = [myObject_1 copy]; | |
assert(myObject_1->_first == myObject_2->_first); | |
assert(myObject_1->_second == myObject_2->_second); | |
assert(myObject_1->_third == myObject_2->_third); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment