objective c - How can a copy of an instance of an object be made for a class which does not adopt NSCopying? -


in contexts (for example, when hooking internals testing) convenient able create copies of instances of classes not adopt nscopying (do not implement -copywithzone:). how can achieved? (note: not enough implement protocol in category because not of class' instance variables visible in header.)

i've tried iterating on object's ivars, , (1) object types recursing (or retaining), and, (2) primitive types, obtaining address of ivar in original instanced , copy that's being made , memcpying buffer starting @ source ivar's address destination ivar's address.

@interface nsobject (addlcopy)  - (id)addl_generatecopydeep:(bool)deepcopy;  @end  @implementation nsobject (addlcopy)  //modified http://stackoverflow.com/a/12265664/1052673 - (void *)addl_ivarpointerforname:(const char *)name {     void *res = null;      ivar ivar = class_getinstancevariable(self.class, name);      if (ivar) {         res = (void *)self + ivar_getoffset(ivar);     }      return res; }   - (id)addl_generatecopydeep:(bool)deepcopy; {     id res = [[self.class alloc] init];      unsigned int count = 0;     ivar *ivars = class_copyivarlist(self.class, &count);     (unsigned int = 0; < count; i++) {         ivar ivar = ivars[i];         //we need try here because of bug nsgetsizeandalignment         //which prevents bitfields being handled , results         //in exception being thrown.  see link more discussion:         //http://lists.apple.com/archives/cocoa-dev/2008/sep/msg00883.html         @try {             nsuinteger size = 0;             const char *encoding = ivar_gettypeencoding(ivar);             nsgetsizeandalignment(encoding, &size, null);             char firstencodingcharacter[2];             strncpy(firstencodingcharacter, encoding, 1);             firstencodingcharacter[1] = 0;             if (strcmp(firstencodingcharacter, "@") == 0) {                 if (deepcopy) {                     id original = object_getivar(self, ivar);                     id copy = [original addl_generatecopydeep:deepcopy];                     object_setivar(res, ivar, copy);                 } else {                     id original = object_getivar(self, ivar);                     object_setivar(res, ivar, original);                 }             } else {                 const char *name = ivar_getname(ivar);                 void *bytessource = [self addl_ivarpointerforname:name];                 void *bytestarget = [res addl_ivarpointerforname:name];                 memcpy(bytestarget, bytessource, size);             }         }         @catch (nsexception *exception) {}         @finally {}     }     free(ivars);      return res; }  @end 

this works somewhat, there couple of glaring issues aware of, not mention i'm not aware of. first of all, not copy ivars inherited superclasses. secondly, not work collections. in addition, because of a bug in nsgetsizeandalignment, not work bitmasks. additionally, fails consider associated objects.

how can instance of object (and objects owns) recursively copied? if not entirely possible (dealing owned object retained , stored in void pointer seems rather difficult if possible), extent can done?

in short, can't.

"deep" copying extremely domain specific problem.

for example, copy delegate of object or leave delegate of copy pointed @ same object (or set nil , require copying client set it)?

for 1 example, there zillion other one-off bits of per-context business logic related copying (which why notion of "deep copying" not implemented on collection classes).

and of above assumes actually have implementation details. classes implemented in frameworks, there no way copy them safely because there isn't data available know bits of memory need copied, less how.

you'll need limit scope , definition of copy operation, pursue solution.


Comments

Popular posts from this blog

routing - AngularJS State management ->load multiple states in one page -

python - GRASS parser() error -

Swift game error message -