views:

1371

answers:

4

I'm making a universal app that will run on both the ipad and the iphone. So far so good, but I have just updated my SDK to ios4 and am wanting to call [[UIScreen mainScreen] scale] (scale is not in the 3.2 sdk and the ipad doesn't have ios4 yet).

I know that I can call [[UIScreen mainScreen] respondsToSelector:@selector(scale)] to find out if I can call it, but I still need to have the function call (and be able to access the return value) in my code so that it can run on the iphone.

EDITED: To be clear, my problem is that there is an error when using the code [[UIScreen mainScreen] scale] when building for 3.2 SDK. This error is "Incompatible types in assignment". So I need to be able to still call this function for 4.0 SDK but still have the project build for 3.2 SDK.

+1  A: 

Well, you could just wrap every call to it in an if statement, like so:

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    //do scale stuff here
}

But a better way (which might require restructuring your whole app, though) is to have separate view controllers for iPad and iPhone.

To get the scale of the device for a cross platform view or something, you could do like this:

CGFloat scale;
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    scale=[[UIScreen mainScreen] scale];
} else {
    scale=1; //only called on iPad.
}

To avoid typing this every time, you could declare a category on UIScreen, which uses this code inside a -realScale method or something.

All of these methods require setting the base SDK to 4.0 (so that you can access the 4.0 APIs) and the minimum iPhone deployment target to 3.2 (so it will run on iPad)

Tom H
This will not work, because [[UIScreen mainScreen] scale] will not build with the 3.2 SDK, which is what my problem is.
DonnaLea
I get an error, not just a warning. But now having a closer look at the error, I think I know how to get around it. The error is: "Incompatible types in assignment".
DonnaLea
Change that, I don't have a clue on how to get around the error
DonnaLea
I'm using something similar but with [UIScreen mainScreen].scale, with Deployment Target = OS 3.0, and it builds without warnings. Runs fine on my iPad (I haven't got another device < 4.0)
Thomas Müller
@Thomas: thanks for the heads up too, Tom H pointed this out to me as well.
DonnaLea
A: 

I ended up finding a solution before asking my question, but it took me forever to figure it out that I decided to post my question and answer in case it helped others.

This is the way that I was able to call the selector scale on the [UIScreen mainScreen] and still have the ipad version build:

CGFloat screenScale;
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    //iphones with the latest SDK should end up in here (and also ipads when they are updated)
    NSMethodSignature * scaleSignature = [UIScreen instanceMethodSignatureForSelector:@selector(scale)];
    NSInvocation * scaleInvocation = [NSInvocation invocationWithMethodSignature:scaleSignature];
    [scaleInvocation setTarget:[UIScreen mainScreen]];
    [scaleInvocation setSelector:@selector(scale)];
    [scaleInvocation invoke];

    NSInteger returnLength = [[scaleInvocation methodSignature] methodReturnLength];
    //good memory management to check this in case anything changed in the future
    if (returnLength == sizeof(CGFloat)) {
        [scaleInvocation getReturnValue:&screenScale];
    } else {
        //default value
        screenScale = 1.0f;
    }
} else {
    //ipad (for now) and other SDK < 4.0 should come here
    screenScale = 1.0f;
}
DonnaLea
What's the point of overcomplicating things?
KennyTM
What was wrong with the stuff I posted? Does it not compile for iPad? If it gives you warnings, you can safely ignore them, but the only time this is better would be if the compiler gave an error.
Tom H
@Tom H: It does give an error, "Incompatible types in assignment".@KennyTM: wanna help out with an uncomplicated answer, then I would be very appreciative.
DonnaLea
Oh sorry, you should set the base SDK in Xcode to 4.0, but iPhone OS minimum deployment target to 3.2. Ask if you need help on how to do that.
Tom H
@Tom H: Thanks so much for your help in guiding me. If you edit your answer with the info on setting the Base SDK to 4.0 and iPhone OS Deployment Target to 3.2 I will mark your answer as the correct answer.
DonnaLea
+1  A: 

if (returnLength = sizeof(CGFloat))

Shouldn't that be if (returnLength == sizeof(CGFloat))?

(I can't post comments.)

Jesper
Thanks Jesper, I updated my answer and code.
DonnaLea
A: 

Argh. All wrong.

  • Set the "Base SDK" to iPhone OS 4.0
  • Set the "iPhone OS Deployment Target" to iPhone OS 3.2.
tc.
I commented on another answer saying that 5 hours ago.
Tom H
Thanks tc, but yes, Tom H pointed this out too, and he's been very helpful with guiding me to the simplest way with his feedback, so I will be marking his answer as correct.
DonnaLea