iOS Question shouldAutorotate causes app to shutdown immediately

CaptKronos

Active Member
Licensed User
I believe I am running into a similar problem to what was reported here https://www.b4x.com/android/forum/threads/method-not-found-audiovol_hide.94401/#content

When I add the following to the bottom of my main module the release version of the app appears for a split second before shutting down. No error appears in the log. Running the debug version of the app and all is fine.
B4X:
#if OBJC
@end
@interface UINavigationController (B4IResize)

@end
@implementation UINavigationController (B4IResize)
- (BOOL)shouldAutorotate
{
  return [(NSNumber*)[B4IObjectWrapper raiseEvent:self :@"_shouldautorotate" :nil] boolValue];
}

#End If

Erel's response to the above referenced thread was to add the code after any other inline code. My main module doesn't have any inline code but several other modules in the project do. In which case, where should I place the shouldAutorotate code?
 

CaptKronos

Active Member
Licensed User
I thought you would ask for that - I'll see what I can do. One thing I didn't mention in my previous post was that the only entry that appears in the log before the app shuts down is:
B4X:
2019-04-29 09:20:53.490148+0100 B4iProject[1197:159096] didFinishLaunchingWithOptions
 
Upvote 0

CaptKronos

Active Member
Licensed User
Ok, I now know how to replicate the problem. Not sure if this is a bug or if I'm doing something that I shouldn't be.

Within the test to determine whether to allow the rotation I have been examining a variable declared in another code module. It is this reference that is causing the problem. If I don't reference another module then all is fine.

Module test.bas:
B4X:
'Code module

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public num As Int=1
End Sub
and main:
B4X:
Sub Main_ShouldAutoRotate As Boolean
    If test.num=1 Then
        Return False
    Else
        Return True
    End If
End Sub

#if OBJC
@end
@interface UINavigationController (B4IResize)

@end
@implementation UINavigationController (B4IResize)
- (BOOL)shouldAutorotate
{
  return [(NSNumber*)[B4IObjectWrapper raiseEvent:self :@"_shouldautorotate" :nil] boolValue];
}

#End If
 
Upvote 0

Filippo

Expert
Licensed User
It is probably called before the modules are ready.

Hi Erel,
you're right!

It took me a few days to find a solution.
I have a couple of apps that run properly without any problem, only this one app wouldn't work.
My solution is to change a variable when you change the orientation and check in sub "Main_ShouldAutoRotate" whether the variable has the value True.

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public App As Application
    Public NavControl As NavigationController
    Private pMain As Page
    Private pnlRoot As Panel
   
    Public OrientationModus As String = "Portrait"
    Private IsSetOrientation As Boolean
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    pMain.Initialize("pMain")
    pMain.RootPanel.LoadLayout("Main")

    pnlRoot.LoadLayout("Page1")
    NavControl.ShowPage(pMain)
   
    IsSetOrientation = False
End Sub

Private Sub pMain_Resize (Width As Float, Height As Float)
    'Log("pMain_Resize")
    Dim r As Rect = pMain.SafeAreaInsets
    pnlRoot.SetLayoutAnimated(0, 1, r.Left, r.Top, Width - r.Right - r.Left, Height - r.Bottom - r.Top)
End Sub

Private Sub pnlRoot_Resize (Width As Float, Height As Float)
   
End Sub

Private Sub pMain_Appear
    Log("Page1_Appear")
    If OrientationModus = "Portrait" Then
        SetOrientation(1)
    Else
        SetOrientation(3)
    End If
   
    IsSetOrientation = True
End Sub

Sub btnSettings_Click
    'Here the variable "OrientationMode" is changed for the orientation.
    mSettings.Show
End Sub

Sub Main_ShouldAutoRotate As Boolean
    Log("Main_ShouldAutoRotate")
    If IsSetOrientation Then
        If DeviceOrientation = "Portrait" And OrientationModus = "Landscape" Then
            Return False
        else If DeviceOrientation <> "Portrait" And OrientationModus = "Portrait" Then
            Return False
        Else
            Return True
        End If
    Else
        Return False
    End If
End Sub

#region Orientation
'0 = "Unknown"
'1 = "Portrait"
'2 = "PortraitUpsideDown"
'3 = "LandscapeLeft"
'4 = "LandscapeRight"
'5 = "FaceUp"
'6 = "FaceDown"
Public Sub SetOrientation(landscape As Int)
    Dim no As NativeObject
    no.Initialize("UIDevice").RunMethod("currentDevice", Null).SetField("orientation", landscape)
    'Log("SetOrientation")
End Sub

Public Sub DeviceOrientation As String
    Dim no As NativeObject
    Dim o As Int = no.Initialize("UIDevice").RunMethod("currentDevice", Null).RunMethod("orientation", Null).AsNumber
    Select o
        Case 0
            Return "Unknown"
        Case 1
            Return "Portrait"
        Case 2
            Return "PortraitUpsideDown"
        Case 3
            Return "LandscapeLeft"
        Case 4
            Return "LandscapeRight"
        Case 5
            Return "FaceUp"
        Case 6
            Return "FaceDown"
        Case Else
            Return "Unknown"
    End Select
End Sub
#End Region

#Region NavigationController
#if OBJC
@end
@interface UINavigationController (B4IResize)

@end
@implementation UINavigationController (B4IResize)
- (BOOL)shouldAutorotate
{
  return [(NSNumber*)[B4IObjectWrapper raiseEvent:self :@"_shouldautorotate" :nil] boolValue];
}

#End If
#End Region
 
Upvote 0
Top