iOS backwards compatibility - alloc/init of a non existent class -
background:
let's i'm developing app using ios 6 sdk. have deployment target set ios 5. can use features 6 in order keep compatibility 5, have have checks in code:
// method available 6, class of someobj existed in 5 if (someobj respondtoselector:@selector(amethod)) { [someobj amethod]; } or
// entire class available 6 if (nsstringfromclass([skstoreproductviewcontroller class]) != nil) { skstoreproductviewcontroller *store = [[skstoreproductviewcontroller alloc] init]; } so far good. these standard ways of doing things, far know.
but found out today new class example, if try , alloc/init object class without checks, doesn't crash on ios 5 have expected rather returns null.
// run on ios 5 device nslog(@"%@", [uicollectionview alloc] init]); why isn't causing crash on ios 5? guess way linker works, expect crash since symbol doesn't exist in version.
the secondary question this: if normal test use nsstringfromclass method, implies can send +class method non-existent class , return null - why/how work?
finally, noticed can create viewcontroller adopts protocol defined in ios 6 , again causes no issues on 5. ?
this behaviour due ns_class_available macro. macro has been implemented on (all?) uikit classes, , return nil class not available. allows check existence of class on specific ios version code:
if ([uicollectionview class]) { // class exists, must ios6+ } now, call [[uicollectionview alloc] init] class method call on nil class, return nil.
to answer secondary question, correct way of checking class existence check if class nil or not, above. nsstringfromclass not needed more.
so, on question 3. surprised one, appears protocol objects compiled directly binary. compiling using latest sdk, code compiles fine , protocol available when running on sdk version has not introduced protocol yet, no linking missing class required. means protocol object valid, , class correctly respond conformstoprotocol: no problems, no matter ios version running. can seen using otool -l on compiled binary, show protocols conformed class , methods. protocols seem live in section called __objc_protolist. output class conforming uicollectionviewdelegate , datasource shown below:
000050a4 0x5cf4 isa 0x5d08 superclass 0x0 cache 0x0 vtable 0x0 data 0x5b30 (struct class_ro_t *) flags 0x80 instancestart 156 instancesize 156 ivarlayout 0x0 name 0x4a0f ttviewcontroller basemethods 0x5b10 (struct method_list_t *) entsize 12 count 2 name 0x3eb8 viewdidload types 0x4955 v8@0:4 imp 0x2620 name 0x3ec4 didreceivememorywarning types 0x4955 v8@0:4 imp 0x2670 baseprotocols 0x5ad8 count 2 list[0] 0x5da0 (struct protocol_t *) isa 0x0 name 0x4997 uicollectionviewdelegate protocols 0x5304 instancemethods 0x0 (struct method_list_t *) classmethods 0x0 (struct method_list_t *) optionalinstancemethods 0x5310 optionalclassmethods 0x0 instanceproperties 0x0 list[1] 0x5dcc (struct protocol_t *) isa 0x0 name 0x49ce uicollectionviewdatasource protocols 0x53d8 instancemethods 0x53e4 (struct method_list_t *) entsize 12 count 2 name 0x394e collectionview:numberofitemsinsection: types 0x455d i16@0:4@8i12 imp 0x0 name 0x3975 collectionview:cellforitematindexpath: types 0x4589 @16@0:4@8@12 imp 0x0 classmethods 0x0 (struct method_list_t *) optionalinstancemethods 0x5404 optionalclassmethods 0x0 instanceproperties 0x0 ivars 0x0 weakivarlayout 0x0 baseproperties 0x0
Comments
Post a Comment