Skip to content

Commit ce73794

Browse files
reuktpoole
authored andcommitted
iOS: Fix building with JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK option
This also fixes an issue where endBackgroundTask wasn't guaranteed to be called after suspended() completed. According to the docs, endBackgroundTask must be called after the task completes.
1 parent f863f16 commit ce73794

File tree

1 file changed

+63
-15
lines changed

1 file changed

+63
-15
lines changed

modules/juce_gui_basics/native/juce_Windowing_ios.mm

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,46 @@ static void oldFn (UIApplication* app)
6363
}
6464
};
6565

66+
/* Each successful call to beginBackgroundTask must be balanced
67+
by a call to endBackgroundTask.
68+
*/
69+
class TaskHandle
70+
{
71+
public:
72+
TaskHandle() = default;
73+
74+
explicit TaskHandle (UIBackgroundTaskIdentifier t)
75+
: task (t) {}
76+
77+
~TaskHandle()
78+
{
79+
if (task != UIBackgroundTaskInvalid)
80+
[[UIApplication sharedApplication] endBackgroundTask:task];
81+
}
82+
83+
TaskHandle (TaskHandle&& other) noexcept
84+
{
85+
swap (other);
86+
}
87+
88+
TaskHandle& operator= (TaskHandle&& other) noexcept
89+
{
90+
TaskHandle { std::move (other) }.swap (*this);
91+
return *this;
92+
}
93+
94+
TaskHandle (const TaskHandle&) = delete;
95+
TaskHandle& operator= (const TaskHandle&) = delete;
96+
97+
private:
98+
void swap (TaskHandle& other) noexcept
99+
{
100+
std::swap (other.task, task);
101+
}
102+
103+
UIBackgroundTaskIdentifier task = UIBackgroundTaskInvalid;
104+
};
105+
66106
struct SceneUtils
67107
{
68108
// This will need to become more sophisticated to enable support for multiple scenes
@@ -80,20 +120,20 @@ static void sceneWillResignActive()
80120
appBecomingInactiveCallbacks.getReference (i)->appBecomingInactive();
81121
}
82122

83-
static void sceneDidEnterBackground()
123+
template <typename Self>
124+
static void sceneDidEnterBackground ([[maybe_unused]] Self* s)
84125
{
85126
if (auto* app = JUCEApplicationBase::getInstance())
86127
{
87128
#if JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK
88-
appSuspendTask = [application beginBackgroundTaskWithName:@"JUCE Suspend Task" expirationHandler:^{
89-
if (appSuspendTask != UIBackgroundTaskInvalid)
90-
{
91-
[application endBackgroundTask:appSuspendTask];
92-
appSuspendTask = UIBackgroundTaskInvalid;
93-
}
94-
}];
129+
s->appSuspendTask = TaskHandle { [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"JUCE Suspend Task"
130+
expirationHandler:^{ s->appSuspendTask = {}; }] };
95131

96-
MessageManager::callAsync ([app] { app->suspended(); });
132+
MessageManager::callAsync ([app, s]
133+
{
134+
app->suspended();
135+
s->appSuspendTask = {};
136+
});
97137
#else
98138
app->suspended();
99139
#endif
@@ -112,10 +152,17 @@ static void sceneWillEnterForeground()
112152

113153
API_AVAILABLE (ios (13.0))
114154
@interface JuceAppSceneDelegate : NSObject<UIWindowSceneDelegate>
155+
{
156+
@public
157+
TaskHandle appSuspendTask;
158+
}
115159
@end
116160

117161
@implementation JuceAppSceneDelegate
118-
SharedResourcePointer<WindowSceneTracker> windowSceneTracker;
162+
{
163+
SharedResourcePointer<WindowSceneTracker> windowSceneTracker;
164+
}
165+
119166
- (void) scene: (UIScene*) scene
120167
willConnectToSession: (UISceneSession*) session
121168
options: (UISceneConnectionOptions*) connectionOptions
@@ -144,7 +191,7 @@ - (void) sceneWillResignActive: (UIScene*) scene
144191

145192
- (void) sceneDidEnterBackground: (UIScene*) scene
146193
{
147-
SceneUtils::sceneDidEnterBackground();
194+
SceneUtils::sceneDidEnterBackground (self);
148195
}
149196

150197
- (void) sceneWillEnterForeground: (UIScene*) scene
@@ -167,7 +214,8 @@ @interface JuceAppStartupDelegate : NSObject <UIApplicationDelegate, UNUserNotif
167214
@interface JuceAppStartupDelegate : NSObject <UIApplicationDelegate>
168215
#endif
169216
{
170-
UIBackgroundTaskIdentifier appSuspendTask;
217+
@public
218+
TaskHandle appSuspendTask;
171219
std::optional<ScopedJuceInitialiser_GUI> initialiser;
172220
}
173221

@@ -216,13 +264,13 @@ - (void) userNotificationCenter: (UNUserNotificationCenter*) center
216264
@end
217265

218266
@implementation JuceAppStartupDelegate
219-
267+
{
220268
NSObject* _pushNotificationsDelegate;
269+
}
221270

222271
- (id) init
223272
{
224273
self = [super init];
225-
appSuspendTask = UIBackgroundTaskInvalid;
226274

227275
#if JUCE_PUSH_NOTIFICATIONS
228276
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
@@ -260,7 +308,7 @@ - (void) applicationWillTerminate: (UIApplication*) application
260308

261309
- (void) applicationDidEnterBackground: (UIApplication*) application
262310
{
263-
SceneUtils::sceneDidEnterBackground();
311+
SceneUtils::sceneDidEnterBackground (self);
264312
}
265313

266314
- (void) applicationWillEnterForeground: (UIApplication*) application

0 commit comments

Comments
 (0)