Skip to content

Commit edaa37a

Browse files
[Feature] macOS support
1 parent edef7a2 commit edaa37a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1857
-89
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,66 @@ public class MainApplication extends FlutterApplication {
275275
}
276276
}
277277
```
278+
279+
#### MacOS
280+
281+
Due to limmitations on MacOS (see https://github.com/flutter/flutter/issues/65222), you need to put this code in your `lib/main.dart` file
282+
283+
**lib/main.dart**
284+
```
285+
@pragma('vm:entry-point')
286+
void _flutterIsolateEntryPoint() => FlutterIsolate.macosIsolateInitialize();
287+
```
288+
289+
**You also need to manually fix plugin registration .**
290+
291+
On iOS, Flutter automatically generates a file `GeneratedPluginRegistrant.m` during build that registers all native code plugins during app start. This allows Flutter to find the platform channels.
292+
293+
The generated file looks something like this:
294+
295+
**GeneratedPluginRegistrant.m**
296+
```
297+
//
298+
// Generated file. Do not edit.
299+
//
300+
301+
// clang-format off
302+
303+
#import "GeneratedPluginRegistrant.h"
304+
305+
#if __has_include(<flutter_downloader/FlutterDownloaderPlugin.h>)
306+
#import <flutter_downloader/FlutterDownloaderPlugin.h>
307+
#else
308+
@import flutter_downloader;
309+
#endif
310+
311+
#if __has_include(<path_provider_foundation/PathProviderPlugin.h>)
312+
#import <path_provider_foundation/PathProviderPlugin.h>
313+
#else
314+
@import path_provider_foundation;
315+
#endif
316+
317+
@implementation GeneratedPluginRegistrant
318+
319+
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
320+
[FlutterDownloaderPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterDownloaderPlugin"]];
321+
[PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]];
322+
}
323+
324+
@end
325+
```
326+
327+
On iOS, this generated file uses Objective-C so `flutter_isolate` can find it using `NSClassFromString(@"GeneratedPluginRegistrant")`.
328+
329+
However, on macOS, this generated file uses Swift & does not use a class, so `NSClassFromString` will not work.
330+
331+
In order to fix plugin registration on MacOS, you need to follow these steps.
332+
333+
1. copy `ios/runner/GeneratedPluginRegistrant.m` from iOS and copy it to `macos/runner/GeneratedPluginRegistrant.m`
334+
2. copy `ios/runner/GeneratedPluginRegistrant.h` from iOS and copy it to `macos/runner/GeneratedPluginRegistrant.h`
335+
3. open Xcode, right click on "Runner" -> "Add Files to Runner" and add macos files from steps 1 & 2
336+
4. delete plugins from `macos/runner/GeneratedPluginRegistrant.m` if they do not support macos
337+
338+
See the example app for a demonstration of this.
339+
340+

example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@
283283
);
284284
runOnlyForDeploymentPostprocessing = 0;
285285
shellPath = /bin/sh;
286-
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
286+
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
287287
};
288288
92A1C2A239E39EB33357B1C8 /* [CP] Embed Pods Frameworks */ = {
289289
isa = PBXShellScriptBuildPhase;
@@ -315,7 +315,7 @@
315315
);
316316
runOnlyForDeploymentPostprocessing = 0;
317317
shellPath = /bin/sh;
318-
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
318+
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
319319
};
320320
9E3AF0DCD678CD20A6F7D6E8 /* [CP] Check Pods Manifest.lock */ = {
321321
isa = PBXShellScriptBuildPhase;

example/lib/main.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
import 'dart:async';
2+
import 'dart:io';
23

34
import 'package:flutter/material.dart';
45
import 'package:flutter_isolate/flutter_isolate.dart';
56
import 'package:path_provider/path_provider.dart';
67
import 'package:flutter_downloader/flutter_downloader.dart';
78

9+
@pragma('vm:entry-point')
10+
void _flutterIsolateEntryPoint() => FlutterIsolate.macosIsolateInitialize();
11+
812
@pragma('vm:entry-point')
913
void isolate2(String arg) {
1014
getTemporaryDirectory().then((dir) async {
1115
print("isolate2 temporary directory: $dir");
1216

13-
await FlutterDownloader.initialize(debug: true);
14-
FlutterDownloader.registerCallback(AppWidget.downloaderCallback);
17+
if (Platform.isMacOS == false) {
18+
await FlutterDownloader.initialize(debug: true);
19+
FlutterDownloader.registerCallback(AppWidget.downloaderCallback);
1520

16-
var url = 'https://raw.githubusercontent.com/rmawatson/flutter_isolate/master/README.md';
21+
var url = 'https://raw.githubusercontent.com/rmawatson/flutter_isolate/master/README.md';
1722

18-
// ignore: unused_local_variable
19-
final taskId = await FlutterDownloader.enqueue(url: url, savedDir: dir.path);
23+
// ignore: unused_local_variable
24+
final taskId = await FlutterDownloader.enqueue(url: url, savedDir: dir.path);
25+
}
2026
});
2127
Timer.periodic(Duration(seconds: 1), (timer) => print("Timer Running From Isolate 2"));
2228
}

example/macos/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Flutter-related
2+
**/Flutter/ephemeral/
3+
**/Pods/
4+
5+
# Xcode-related
6+
**/dgph
7+
**/xcuserdata/
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2+
#include "ephemeral/Flutter-Generated.xcconfig"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2+
#include "ephemeral/Flutter-Generated.xcconfig"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//
2+
// Generated file. Do not edit.
3+
//
4+
5+
import FlutterMacOS
6+
import Foundation
7+
8+
import flutter_isolate
9+
import path_provider_foundation
10+
11+
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
12+
FlutterIsolatePluginMacOS.register(with: registry.registrar(forPlugin: "FlutterIsolatePluginMacOS"))
13+
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
14+
}

example/macos/Podfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
platform :osx, '10.14'
2+
3+
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4+
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
5+
6+
project 'Runner', {
7+
'Debug' => :debug,
8+
'Profile' => :release,
9+
'Release' => :release,
10+
}
11+
12+
def flutter_root
13+
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
14+
unless File.exist?(generated_xcode_build_settings_path)
15+
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
16+
end
17+
18+
File.foreach(generated_xcode_build_settings_path) do |line|
19+
matches = line.match(/FLUTTER_ROOT\=(.*)/)
20+
return matches[1].strip if matches
21+
end
22+
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
23+
end
24+
25+
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
26+
27+
flutter_macos_podfile_setup
28+
29+
target 'Runner' do
30+
use_frameworks!
31+
use_modular_headers!
32+
33+
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
34+
target 'RunnerTests' do
35+
inherit! :search_paths
36+
end
37+
end
38+
39+
post_install do |installer|
40+
installer.pods_project.targets.each do |target|
41+
flutter_additional_macos_build_settings(target)
42+
end
43+
end

0 commit comments

Comments
 (0)