Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

namanhams

macrumors regular
Original poster
Jun 3, 2009
153
0
iOS 5 introduces some new properties in the Address Book, for eg : kABPersonSocialProfileProperty.

But it seems that there's something wrong. The app will just crash if i do something like this in iOS 4 :

Code:
ABAddressBookRef addressBook = ABAddressBookCreate();

CGFloat iOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if(iOSVersion >= 5.0) {
    NSLog(@"We are in iOS 5");
    NSLog(@"%d", kABPersonSocialProfileProperty);
}

If i run the code in iOS 4, the code inside the IF block never execute, but the app just crashes in the 2nd NSLog.

If i replace kABPersonSocialProfileProperty with any other property that appears in iOS 4, everything is fine.


So my guess is that the compiler does something wrongly.
Anyone can enlighten me on this ? Thanks.
 
2nd NSLog, and that didn't give you an hint?
You're trying to log a double, from a property which probably isn't, the compiler should show it, but hte debugger got worse in 4.2.
So basically, you should check what the kABPersonSocialProfileProperty() property gives back.
 
But isn't the point that if version < 5.0, neither of the NSLog calls should happen?

OP, is this exactly your code? You copied and pasted from XCode into the post right? You didn't just retype the code or paraphrase the code?
 
2nd NSLog, and that didn't give you an hint?
You're trying to log a double, from a property which probably isn't, the compiler should show it, but hte debugger got worse in 4.2.
So basically, you should check what the kABPersonSocialProfileProperty() property gives back.

kABPersonSocialProfileProperty is of type ABPropertyID, which is an integer.

But as i said, those 2 NSLog never executes in iOS 4.

----------

But isn't the point that if version < 5.0, neither of the NSLog calls should happen?

OP, is this exactly your code? You copied and pasted from XCode into the post right? You didn't just retype the code or paraphrase the code?

Hi,

Yes that's exactly my code. Me and my colleague spent the whole afternoon, comment out all other lines, and just keep those lines.
 
(Removed all the assembly stuff, it was x86 assembly for the simulator. Embarrassing.)

What happens if you move the the two NSLogs out into a separate method?
 
Last edited:
But as i said, those 2 NSLog never executes in iOS 4.
Bigger or Equal to IOS5, and you run it in iOS4? how will it ever go into the the IF Function?
And if it crashes on an NSLog line, means you are doing it wrong, if it's an integer, do %i not, %d. Also, when you try to type a float, just put 'f' behind your number.
Just some pointers to set you on your way.
 
(Removed all the assembly stuff, it was x86 assembly for the simulator. Embarrassing.)

What happens if you move the the two NSLogs out into a separate method?


Oh i forgot to mention that, if i write a method like this :

Code:
- (int) workAround {
    return kABPersonSocialProfileProperty;
}

and replace the 2nd NSLog with :

Code:
NSLog(@"%d", [self test]);

Then it works.

But to me, it's even clearer as a sign of Compiler issue.
 
That seems to be reinforce my theory that it's a problem with the branch predictor and the CPU pipeline executing the code to resolve the extern const int.

You are running undefined code under iOS 4 because the extern const doesn't exist. By undefined code I mean the behaviour of the code is undefined. As others a fond of saying here, your code could do anything from behaving as expected through to crashing though to launching the world's nukes, or anything or everything in between.

The defined status of code is not related to whether the code would actually execute at runtime. For example, the Objective-C compiler could quite reasonably and allowably put the machine code to resolve the extern const int at the top of the method, or even at the very start of the execution of your program. It can do that because it's const, and therefore won't change over the life of the program.

It can't though, unfortunately for you, inline the const int because it's extern. It's guaranteed not to change over the life one invocation of your program, it's not guaranteed not to change over different invocations of your program. So the compiler cannot replace the reference to the int with the int itself.


I would say that if it's working for you to move iOS 5 dependent code into methods separate from iOS 4 code, then do that and be thankful that even that works for you.
 
Bigger or Equal to IOS5, and you run it in iOS4? how will it ever go into the the IF Function?
And if it crashes on an NSLog line, means you are doing it wrong, if it's an integer, do %i not, %d. Also, when you try to type a float, just put 'f' behind your number.
Just some pointers to set you on your way.

FYI, those 2 lines never execute. If you dont know why, create a new project and paste those lines in. Run it in iOS 4.x

----------

That seems to be reinforce my theory that it's a problem with the branch predictor and the CPU pipeline executing the code to resolve the extern const int.

You are running undefined code under iOS 4 because the extern const doesn't exist. By undefined code I mean the behaviour of the code is undefined. As others a fond of saying here, your code could do anything from behaving as expected through to crashing though to launching the world's nukes, or anything or everything in between.

The defined status of code is not related to whether the code would actually execute at runtime. For example, the Objective-C compiler could quite reasonably and allowably put the machine code to resolve the extern const int at the top of the method, or even at the very start of the execution of your program. It can do that because it's const, and therefore won't change over the life of the program.

It can't though, unfortunately for you, inline the const int because it's extern. It's guaranteed not to change over the life one invocation of your program, it's not guaranteed not to change over different invocations of your program. So the compiler cannot replace the reference to the int with the int itself.


I would say that if it's working for you to move iOS 5 dependent code into methods separate from iOS 4 code, then do that and be thankful that even that works for you.


Seems that what you say is correct. Although i dont know the reason, but in fact sometimes it works, sometimes it fails.

Can i say that it's a bug of XCode 4.2 or iOS 5 ? Thanks.
 
I know why, that's why i'm wondering why he is complaining it isn't executing, because it wil only trigger on iOS 5 and bigger.
So that's normal no?

I do not complain why it's not executing. Of course it never executes on iOS 4.x
It doesn't execute, but it crashes there. That's what i dont know why.
Please read my first post again.
 
I do not complain why it's not executing. Of course it never executes on iOS 4.x
It doesn't execute, but it crashes there. That's what i dont know why.
Please read my first post again.

I see, and if you run through the debugger, and you do a next step on the if, does it actually go over the line, and crashes then,or does it crash on the next step?
Just interested, since i don't have time to check it out myself atm.
 
I see, and if you run through the debugger, and you do a next step on the if, does it actually go over the line, and crashes then,or does it crash on the next step?
Just interested, since i don't have time to check it out myself atm.

Uhm so what should i do if :
- I want to make use of iOS 5 new features, which is the kABPersonSocialProfileProperty
- My code should also support iOS 4.x

I'm a bit confused now as from what i see, i dont do anything wrong.

----------

I see, and if you run through the debugger, and you do a next step on the if, does it actually go over the line, and crashes then,or does it crash on the next step?
Just interested, since i don't have time to check it out myself atm.

No it never steps into the IF block. But the behavior for all other code is undefined. Sometimes it run, sometimes it doesn't.
 
Uhm so what should i do if :
- I want to make use of iOS 5 new features, which is the kABPersonSocialProfileProperty
- My code should also support iOS 4.x

I'm a bit confused now as from what i see, i dont do anything wrong.

I've not done it for iOS, but I have done it for Mac OS X.

The way I did it was by careful class design. I designed a class that had legacy code in it and a subclass that overrode the necessary methods with updated code for the new OS. I would then either init the legacy OS class or the new OS class depending on the OS version. This worked, I guess, because the CPU never went anywhere near new OS code when the app ran on a legacy OS.


Although I've just thought of weak linking. I'll get back to you.


Sorry, I was thinking of TN2064. But my testing seems to show that weak linking is not implemented in iOS's runtime linker.
 
Last edited:
I've not done it for iOS, but I have done it for Mac OS X.

The way I did it was by careful class design. I designed a class that had legacy code in it and a subclass that overrode the necessary methods with updated code for the new OS. I would then either init the legacy OS class or the new OS class depending on the OS version. This worked, I guess, because the CPU never went anywhere near new OS code when the app ran on a legacy OS.


Although I've just thought of weak linking. I'll get back to you.


Sorry, I was thinking of TN2064. But my testing seems to show that weak linking is not implemented in iOS's runtime linker.

Thanks a lot for your answer ! I've decided to drop those features since i can not be sure whether it will crash or not.
 
Weak linking is absolutely supported in iOS.

Interesting. I couldn't get the symbol to resolve to NULL when it wasn't present in the framework. It would only signal bad access. I tried re-declaring the extern with __attribute__((weak_import)).

It's also interesting the availability macros for iOS doesn't expand to __attribute__((weak_import)) like the Mac OS X availability macros do.

Can you supply any evidence that iOS supports weak linking? Or more usefully, do you know a way for kABPersonSocialProfileProperty to be weak linked? It's a shame that the OP has dropped the iOS 5 support in his app.
 
http://www.marco.org/2010/11/22/supporting-older-versions-of-ios-while-using-new-apis

I'm not sure if it is possible to weak link an individual constant defined by a particular framework.

I'm an idiot sometimes. It became obvious when I traced through the code at the granularity of the machine code instruction.

&kABPersonSocialProfileProperty is NULL when running on iOS 4 because of weak linking and not NULL on iOS 5.

The problem is that kABPersonSocialProfileProperty is effectively *(&kABPersonSocialProfileProperty). So if &kABPersonSocialProfileProperty is NULL, then of course kABPersonSocialProfileProperty is going to result in a bad access signal.

Unfortunately none of this is going to help the OP.


What are others doing when they use new iOS features while still maintaining backwards compatibility?
 
Effective use of respondsToSelector: as well as NSClassFromString() works for me.

If i'm not wrong, those are used when you want to support classes or methods which may be not available in older iOS. My case is a constant string.
If you know how to deal with my case please tell me. Thanks.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.