views:

370

answers:

2

Hello, I'm here again!

I have a deadline soon and I have very annoying bug in front of me and no ideas, how to fix it. The problem is, that sometimes device doesn't know what it's orientation is before it has been rotated and so it messes up frames in conditional statements:

 if (orient == UIInterfaceOrientationPortrait || orient == 0){ 
  r = CGRectMake(0.0, 0.0, 320.0, 480.0);
        // draw stuff
    } else {
  r = CGRectMake(0.0, 0.0, 480.0, 320.0);
        // draw stuff
    }

This bug can be easily reproduced if I keep device on the table or in hands (horizontal position) and run my application, it draws landscape-like rectangles in portrait type screen.

My questions are: can I somehow get the right orientation in this kind of situation? Too bad it can not be reproduced in simulator, so I'm not sure if the code I pasted is responsible for this bug, but that is the place where I fix view frames according to orientation. Maybe there's another (proper) way to do that? And maybe I can force application to be in portrait mode until rotation event will be fired?

+1  A: 

The sensor which determines the device's orientation is neither infallible nor intelligent. If you set the phone down on the table and then walk around it, how is it supposed to know that it's upside down?

Azeem.Butt
I understand now. In my case I just need to know that it is on the table. How can I do that?
sniurkst
+1  A: 

I don't think it is a bug. When the iPhone is sitting on the table all the gravity is meassured along the Z axis. To determine device orientation x-y axis are used, but no acceleration is measured alongside of them in your scenario.

EDIT: Further explanations:

This image shows how the Axis are oriented on the iPhone: alt text

So when you have the iPhone lying on the back, an acceleration of -1g is applied on the z axis. To receive the measured accelerations simply register a delegate implementing UIAccelerometerDelegate with the UIAccelerometershared instance. See the AccelerometerGraph sample how this is done.

To determine if the iphone sits on the table do something like this:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
    {

    // lowPass filter first

    // now choose orientation
      if (fabs([acceleration z]) >= 0.9) // sitting on the table: choose new mode or lock current mode
      if (fabs([acceleration y]) >= 0.9) // probably portrait mode
      if (fabs([acceleration x]) >= 0.9) // probably landscape mode

    }

The accelerometer precision is 18mG = 0.018G so take that into account. Also you need to isolate yourself from the effects of instant movement changes, a simple LowPass filter fits this bill perfectly. The AccelerometerGraph sample shows how to implement such a filter.

Also choose a very low updateInterval if you don't need a lot of precision, 30Hz should be okay for your purposes.

Johannes Rudolph
Thanks for answer, but can you give some ideas how can I know that Iphone is "on the table" and so it's orientation should be portrait, not landscape as it tries to be in my application?
sniurkst
well, it already is in my answer (acceleration along z axis amounts to 1g +- a little bit :-) )
Johannes Rudolph
You'd need to use UIAccelerometer to get events telling you what position the phone is in.
Jason