Flutter iOS Embedder
FlutterNSBundleUtils.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <Foundation/Foundation.h>
6 
8 
10 
11 const NSString* kDefaultAssetPath = @"Frameworks/App.framework/flutter_assets";
12 static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath);
13 
14 NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL* searchURL) {
15  NSDirectoryEnumerator<NSURL*>* frameworkEnumerator = [NSFileManager.defaultManager
16  enumeratorAtURL:searchURL
17  includingPropertiesForKeys:nil
18  options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
19  NSDirectoryEnumerationSkipsHiddenFiles
20  // Skip directories where errors are encountered.
21  errorHandler:nil];
22 
23  for (NSURL* candidate in frameworkEnumerator) {
24  NSBundle* flutterFrameworkBundle = [NSBundle bundleWithURL:candidate];
25  if ([flutterFrameworkBundle.bundleIdentifier isEqualToString:flutterFrameworkBundleID]) {
26  return flutterFrameworkBundle;
27  }
28  }
29  return nil;
30 }
31 
33  NSBundle* mainBundle = NSBundle.mainBundle;
34  // App extension bundle is in <AppName>.app/PlugIns/Extension.appex.
35  if ([mainBundle.bundleURL.pathExtension isEqualToString:@"appex"]) {
36  // Up two levels.
37  return [NSBundle bundleWithURL:mainBundle.bundleURL.URLByDeletingLastPathComponent
38  .URLByDeletingLastPathComponent];
39  }
40  return mainBundle;
41 }
42 
43 NSBundle* FLTFrameworkBundleWithIdentifier(NSString* flutterFrameworkBundleID) {
44  NSBundle* appBundle = FLTGetApplicationBundle();
45  NSBundle* flutterFrameworkBundle =
46  FLTFrameworkBundleInternal(flutterFrameworkBundleID, appBundle.privateFrameworksURL);
47  if (flutterFrameworkBundle == nil) {
48  // Fallback to slow implementation.
49  flutterFrameworkBundle = [NSBundle bundleWithIdentifier:flutterFrameworkBundleID];
50  }
51  if (flutterFrameworkBundle == nil) {
52  flutterFrameworkBundle = NSBundle.mainBundle;
53  }
54  return flutterFrameworkBundle;
55 }
56 
57 NSString* FLTAssetPath(NSBundle* bundle) {
58  return [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"] ?: kDefaultAssetPath;
59 }
60 
61 NSString* FLTAssetsPathFromBundle(NSBundle* bundle) {
62  NSString* relativeAssetsPath = FLTAssetPath(bundle);
63  NSString* flutterAssetsPath = GetFlutterAssetsPathFromBundle(bundle, relativeAssetsPath);
64  if (flutterAssetsPath.length == 0) {
65  flutterAssetsPath = GetFlutterAssetsPathFromBundle(NSBundle.mainBundle, relativeAssetsPath);
66  }
67  return flutterAssetsPath;
68 }
69 
70 static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath) {
71  // Use the raw path solution so that asset path can be returned from unloaded bundles.
72  // See https://github.com/flutter/engine/pull/46073
73  NSString* assetsPath = [bundle pathForResource:relativeAssetsPath ofType:nil];
74  if (assetsPath.length == 0) {
75  // In app extension, using full relative path (kDefaultAssetPath)
76  // returns nil when the app bundle is not loaded. Try to use
77  // the sub folder name, which can successfully return a valid path.
78  assetsPath = [bundle pathForResource:@"flutter_assets" ofType:nil];
79  }
80  return assetsPath;
81 }
FLTFrameworkBundleWithIdentifier
NSBundle * FLTFrameworkBundleWithIdentifier(NSString *flutterFrameworkBundleID)
Definition: FlutterNSBundleUtils.mm:43
FLTFrameworkBundleInternal
NSBundle * FLTFrameworkBundleInternal(NSString *flutterFrameworkBundleID, NSURL *searchURL)
Definition: FlutterNSBundleUtils.mm:14
GetFlutterAssetsPathFromBundle
static NSString * GetFlutterAssetsPathFromBundle(NSBundle *bundle, NSString *relativeAssetsPath)
Definition: FlutterNSBundleUtils.mm:70
FlutterMacros.h
FLTAssetPath
NSString * FLTAssetPath(NSBundle *bundle)
Definition: FlutterNSBundleUtils.mm:57
FLTAssetsPathFromBundle
NSString * FLTAssetsPathFromBundle(NSBundle *bundle)
Definition: FlutterNSBundleUtils.mm:61
kDefaultAssetPath
const FLUTTER_ASSERT_ARC NSString * kDefaultAssetPath
Definition: FlutterNSBundleUtils.mm:11
FLTGetApplicationBundle
NSBundle * FLTGetApplicationBundle()
Definition: FlutterNSBundleUtils.mm:32
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13