0

I would like to defer auto rotating the user interface until the device has settled on an orientation for a number of seconds, rather than driving the user insane and flicking willy nilly whenever they tilt the device a few degrees off axis by mistake.

the closest i can get to this (which is by no means what I want, as it locks the UI) is:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.

    [NSThread sleepForTimeInterval:2.0];
    return YES;
}

what i would like to do is use something like this - which works in principle, by checking the console log, but i need the appropriate line of code that has been commented out.

-(void) deferredAutorotateToInterfaceOrientation:(NSTimer *) timer { 
    autoRotationTimer = nil;

    UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)[timer.userInfo integerValue];

    NSLog(@"switching to new orientation %d now",interfaceOrientation);

    // replace this with code to induce manual orientation switch here.
    //[self forceAutoRotateToInterfaceOrientation:interfaceOrientation];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    [autoRotationTimer invalidate];

    autoRotationTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self 
                                   selector:@selector(deferredAutorotateToInterfaceOrientation:) userInfo:[NSNumber numberWithInt:(int)interfaceOrientation ] repeats:NO];

    NSLog(@"denying autorotate, deffering switch to orientation %d by 2 seconds",interfaceOrientation);

    return NO;
}

I realize there are sometimes many ways to do things, so if this approach is not the most efficient, and someone can suggest another way to do this, I am all ears. My main criteria is I want to delay the onset of autorotation, whilst keeping a responsive user interface if indeed they have only leaned to the left slightly because they are in a bus that just went around a corner etc.

EDIT: I found a solution which may not be app store friendly, however i am a few weeks away from completion, and someone may answer this in the meantime. this works calls an undocumented method. the (UIPrintInfoOrientation) typecast is just to suppress the compiler warning, and does not affect the value being passed.

-(void ) forceUIOrientationInterfaceOrientation:(UIDeviceOrientation) interfaceMode {
    [(id)[UIDevice currentDevice] setOrientation:(UIPrintInfoOrientation) interfaceMode];
}

full implementation which includes re-entrance negation is as follows:

- (void)viewDidLoad {
    [super viewDidLoad];
    acceptNewAutoRotation = YES;
}

-(void ) forceUIOrientationInterfaceOrientation:(UIDeviceOrientation) interfaceMode {
    [(id)[UIDevice currentDevice] setOrientation:(UIPrintInfoOrientation) interfaceMode];
}

-(void) deferredAutorotateToInterfaceOrientation:(NSTimer *) timer { 
    autoRotationTimer = nil;

    acceptNewAutoRotation = YES;

    [self forceUIOrientationInterfaceOrientation:[[UIDevice currentDevice] orientation]];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    [autoRotationTimer invalidate];

    if (acceptNewAutoRotation) {
        autoRotationTimer = nil;
         acceptNewAutoRotation = NO;
        return YES;
    } else {     

        autoRotationTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self 
                                                           selector:@selector(deferredAutorotateToInterfaceOrientation:) userInfo:[NSNumber numberWithInt:(int)interfaceOrientation ] repeats:NO];


        return  NO;
    }    

}
unsynchronized
  • 4,828
  • 2
  • 31
  • 43
  • as mentioned in the question i have now edited, i have found a temporary solution that might not fly with the app store, so if someone has a better method, please let me know. – unsynchronized Oct 03 '11 at 05:58

2 Answers2

0

To do this with public APIs, you probably would have to forget about autorotation, and do all your own view transforms manually based on filtered (not just delayed!) accelerometer input.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • decided to remove this functionality entirely as user can lock the rotation if it becomes an issue. apple may decide to incorporate this sort of feature in the OS internally, which is probably where it belongs rather than on a per app basis. – unsynchronized Nov 05 '11 at 22:37
0

I have not tested this and it may not work at all but you can try this out:

start out self.rotate = NO; then:

- (void)shouldRotateTo:(UIInteraceOrientation *)interfaceOrientation {
    self.rotate = YES;
    // or test interfaceOrientation and assign accordingly.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    bool rot = self.rotate;
    self.rotate = NO
    [self performSelector:selector(shouldRotateTo:) withObject:[NSNumber numberWithInt:interfaceOrientation] afterDelay:2.0];
    return rot;
}

Parameter interfaceOrientation is an enum (UIInteraceOrientation) so wrap it in an NSNumber when passing.

chown
  • 51,908
  • 16
  • 134
  • 170