0x00 引入
蘋果沒有公開強制設(shè)置物理設(shè)備方向的方法。
SO上能找到的最多的方法是:
NSNumber orientation = [NSNumber numberWithInt:targetOrientation];
[[UIDevice currentDevice] setValue:orientation forKey:@"orientation"]
這種方法使用KVO機制,間接地使用了蘋果的私有方法。不過多次實測驗證不影響上架審核。
0x01 問題
上述setValue:forKey:方法有一個問題,如果將要設(shè)置的目標(biāo)方向與當(dāng)前物理設(shè)備的方向一樣的話,上述方法可能會不起作用。
例如:兩個視圖控制器A和B,其中A支持橫屏和豎屏, B僅支持橫屏,當(dāng)從Portrait方向由 A push到 B時,強制設(shè)置B的方向為LandscapeRight,從B返回到A時,我們還希望A是Portrait方向。但是如果我們在B視圖控制器上把設(shè)備旋轉(zhuǎn)至Portrait方向時,然后在返回A,使用上述setValue:forKey:的方法強制把物理設(shè)備方向設(shè)置為Portrait時就會不起作用,因為此時物理設(shè)備的方向與將要設(shè)置的目標(biāo)方向是一樣的。
0x02 原因猜想
如果當(dāng)前物理設(shè)備的方向與要設(shè)置的目標(biāo)方向一致時,系統(tǒng)可能覺得沒有必要進(jìn)行任何操作(按照正常的邏輯來考慮,好像應(yīng)該是這樣),在系統(tǒng)內(nèi)部實現(xiàn)上可能就直接return了(未考證,猜測)。然而業(yè)務(wù)的需求常常會不僅僅于此,我們期望能在任意當(dāng)前方向把物理設(shè)備設(shè)置為任意目標(biāo)方向。
0x03 問題解決
既然直接通過setValue:forKey:設(shè)置目標(biāo)方向不起作用,那么猜想可以先設(shè)置一個unknown方向欺騙系統(tǒng),然后再設(shè)置目標(biāo)方向,這時目標(biāo)方向跟unknown方向是不同,系統(tǒng)就會生效這種設(shè)置。
下面是一個強制設(shè)置設(shè)備方向的方法:
- (void)forceToOrientation:(UIDeviceOrientation)orientation
{
NSNumber *orientationUnknown = [NSNumber numberWithInt:0];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
NSNumber *orientationTarget = [NSNumber numberWithInt:orientation];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
}
在iOS7,8,9上驗證,可以完美解決0x01例子中的問題。
在蘋果不提供有效的公開API時,這種方法基本可以達(dá)到這樣的目標(biāo):在任意當(dāng)前方向把物理設(shè)備設(shè)置為任意目標(biāo)方向。