Reland "Reverts "[ios] Fix app extension not able to find assets from… (flutter/engine#46329)

Relands https://github.com/flutter/engine/pull/46283

The original PR had a bug where the relative assets path is reset after not being found in the `bundle`. It should not be reset unless it was not found inside the info.plist in `bundle`

Fixes https://github.com/flutter/flutter/issues/124292

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
Chris Yang 2023-09-27 17:02:04 -07:00 committed by GitHub
parent e333e342c8
commit e2bc37bba7
32 changed files with 1177 additions and 17 deletions

View File

@ -9,6 +9,7 @@
FLUTTER_ASSERT_ARC
const NSString* kDefaultAssetPath = @"Frameworks/App.framework/flutter_assets";
static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath);
NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL* searchURL) {
NSDirectoryEnumerator<NSURL*>* frameworkEnumerator = [NSFileManager.defaultManager
@ -29,7 +30,7 @@ NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL*
}
NSBundle* FLTGetApplicationBundle() {
NSBundle* mainBundle = [NSBundle mainBundle];
NSBundle* mainBundle = NSBundle.mainBundle;
// App extension bundle is in <AppName>.app/PlugIns/Extension.appex.
if ([mainBundle.bundleURL.pathExtension isEqualToString:@"appex"]) {
// Up two levels.
@ -48,7 +49,7 @@ NSBundle* FLTFrameworkBundleWithIdentifier(NSString* flutterFrameworkBundleID) {
flutterFrameworkBundle = [NSBundle bundleWithIdentifier:flutterFrameworkBundleID];
}
if (flutterFrameworkBundle == nil) {
flutterFrameworkBundle = [NSBundle mainBundle];
flutterFrameworkBundle = NSBundle.mainBundle;
}
return flutterFrameworkBundle;
}
@ -58,13 +59,23 @@ NSString* FLTAssetPath(NSBundle* bundle) {
}
NSString* FLTAssetsPathFromBundle(NSBundle* bundle) {
NSString* flutterAssetsPath = FLTAssetPath(bundle);
NSString* relativeAssetsPath = FLTAssetPath(bundle);
NSString* flutterAssetsPath = GetFlutterAssetsPathFromBundle(bundle, relativeAssetsPath);
if (flutterAssetsPath.length == 0) {
flutterAssetsPath = GetFlutterAssetsPathFromBundle(NSBundle.mainBundle, relativeAssetsPath);
}
return flutterAssetsPath;
}
static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath) {
// Use the raw path solution so that asset path can be returned from unloaded bundles.
// See https://github.com/flutter/engine/pull/46073
NSString* assetsPath = [bundle pathForResource:flutterAssetsPath ofType:@""];
NSString* assetsPath = [bundle pathForResource:relativeAssetsPath ofType:nil];
if (assetsPath.length == 0) {
assetsPath = [[NSBundle mainBundle] pathForResource:flutterAssetsPath ofType:@""];
// In app extension, using full relative path (kDefaultAssetPath)
// returns nil when the app bundle is not loaded. Try to use
// the sub folder name, which can successfully return a valid path.
assetsPath = [bundle pathForResource:@"flutter_assets" ofType:nil];
}
return assetsPath;
}

View File

@ -93,21 +93,34 @@ FLUTTER_ASSERT_ARC
id mockBundle = OCMClassMock([NSBundle class]);
OCMStub([mockBundle objectForInfoDictionaryKey:@"FLTAssetsPath"]).andReturn(@"foo/assets");
NSString* resultAssetsPath = @"path/to/foo/assets";
OCMStub([mockBundle pathForResource:@"foo/assets" ofType:@""]).andReturn(resultAssetsPath);
OCMStub([mockBundle pathForResource:@"foo/assets" ofType:nil]).andReturn(resultAssetsPath);
NSString* path = FLTAssetsPathFromBundle(mockBundle);
XCTAssertEqualObjects(path, @"path/to/foo/assets");
}
{
// Found asset path in info.plist, is not overriden by main bundle
id mockBundle = OCMClassMock([NSBundle class]);
id mockMainBundle = OCMPartialMock(NSBundle.mainBundle);
OCMStub([mockBundle objectForInfoDictionaryKey:@"FLTAssetsPath"]).andReturn(@"foo/assets");
OCMStub([mockMainBundle objectForInfoDictionaryKey:@"FLTAssetsPath"]).andReturn(nil);
NSString* resultAssetsPath = @"path/to/foo/assets";
OCMStub([mockBundle pathForResource:@"foo/assets" ofType:nil]).andReturn(resultAssetsPath);
NSString* path = FLTAssetsPathFromBundle(mockBundle);
XCTAssertEqualObjects(path, @"path/to/foo/assets");
[mockMainBundle stopMocking];
}
{
// No asset path in info.plist, defaults to main bundle
id mockBundle = OCMClassMock([NSBundle class]);
id mockMainBundle = OCMPartialMock([NSBundle mainBundle]);
NSString* resultAssetsPath = @"path/to/foo/assets";
OCMStub([mockBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:@""])
OCMStub([mockBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:nil])
.andReturn(nil);
OCMStub([mockMainBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:@""])
OCMStub([mockMainBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:nil])
.andReturn(resultAssetsPath);
NSString* path = FLTAssetsPathFromBundle(mockBundle);
XCTAssertEqualObjects(path, @"path/to/foo/assets");
[mockMainBundle stopMocking];
}
}

View File

@ -0,0 +1,372 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
686382C62ABE173000E27AAD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 686382C52ABE173000E27AAD /* AppDelegate.m */; };
686382C92ABE173000E27AAD /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 686382C82ABE173000E27AAD /* SceneDelegate.m */; };
686382CC2ABE173000E27AAD /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 686382CB2ABE173000E27AAD /* ViewController.m */; };
686382CF2ABE173000E27AAD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 686382CD2ABE173000E27AAD /* Main.storyboard */; };
686382D12ABE173000E27AAD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 686382D02ABE173000E27AAD /* Assets.xcassets */; };
686382D42ABE173000E27AAD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 686382D22ABE173000E27AAD /* LaunchScreen.storyboard */; };
686382D72ABE173000E27AAD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 686382D62ABE173000E27AAD /* main.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
686382C12ABE172F00E27AAD /* FlutterAppExtensionTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlutterAppExtensionTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
686382C42ABE173000E27AAD /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
686382C52ABE173000E27AAD /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
686382C72ABE173000E27AAD /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = "<group>"; };
686382C82ABE173000E27AAD /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = "<group>"; };
686382CA2ABE173000E27AAD /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
686382CB2ABE173000E27AAD /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
686382CE2ABE173000E27AAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
686382D02ABE173000E27AAD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
686382D32ABE173000E27AAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
686382D52ABE173000E27AAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
686382D62ABE173000E27AAD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
686382BE2ABE172F00E27AAD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
686382B82ABE172F00E27AAD = {
isa = PBXGroup;
children = (
686382C32ABE173000E27AAD /* FlutterAppExtensionTestHost */,
686382C22ABE172F00E27AAD /* Products */,
);
sourceTree = "<group>";
};
686382C22ABE172F00E27AAD /* Products */ = {
isa = PBXGroup;
children = (
686382C12ABE172F00E27AAD /* FlutterAppExtensionTestHost.app */,
);
name = Products;
sourceTree = "<group>";
};
686382C32ABE173000E27AAD /* FlutterAppExtensionTestHost */ = {
isa = PBXGroup;
children = (
686382C42ABE173000E27AAD /* AppDelegate.h */,
686382C52ABE173000E27AAD /* AppDelegate.m */,
686382C72ABE173000E27AAD /* SceneDelegate.h */,
686382C82ABE173000E27AAD /* SceneDelegate.m */,
686382CA2ABE173000E27AAD /* ViewController.h */,
686382CB2ABE173000E27AAD /* ViewController.m */,
686382CD2ABE173000E27AAD /* Main.storyboard */,
686382D02ABE173000E27AAD /* Assets.xcassets */,
686382D22ABE173000E27AAD /* LaunchScreen.storyboard */,
686382D52ABE173000E27AAD /* Info.plist */,
686382D62ABE173000E27AAD /* main.m */,
);
path = FlutterAppExtensionTestHost;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
686382C02ABE172F00E27AAD /* FlutterAppExtensionTestHost */ = {
isa = PBXNativeTarget;
buildConfigurationList = 686382DA2ABE173000E27AAD /* Build configuration list for PBXNativeTarget "FlutterAppExtensionTestHost" */;
buildPhases = (
686382BD2ABE172F00E27AAD /* Sources */,
686382BE2ABE172F00E27AAD /* Frameworks */,
686382BF2ABE172F00E27AAD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = FlutterAppExtensionTestHost;
productName = FlutterAppExtensionTestHost;
productReference = 686382C12ABE172F00E27AAD /* FlutterAppExtensionTestHost.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
686382B92ABE172F00E27AAD /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastUpgradeCheck = 1500;
TargetAttributes = {
686382C02ABE172F00E27AAD = {
CreatedOnToolsVersion = 15.0;
};
};
};
buildConfigurationList = 686382BC2ABE172F00E27AAD /* Build configuration list for PBXProject "FlutterAppExtensionTestHost" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 686382B82ABE172F00E27AAD;
productRefGroup = 686382C22ABE172F00E27AAD /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
686382C02ABE172F00E27AAD /* FlutterAppExtensionTestHost */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
686382BF2ABE172F00E27AAD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
686382D42ABE173000E27AAD /* LaunchScreen.storyboard in Resources */,
686382D12ABE173000E27AAD /* Assets.xcassets in Resources */,
686382CF2ABE173000E27AAD /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
686382BD2ABE172F00E27AAD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
686382CC2ABE173000E27AAD /* ViewController.m in Sources */,
686382C62ABE173000E27AAD /* AppDelegate.m in Sources */,
686382D72ABE173000E27AAD /* main.m in Sources */,
686382C92ABE173000E27AAD /* SceneDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
686382CD2ABE173000E27AAD /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
686382CE2ABE173000E27AAD /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
686382D22ABE173000E27AAD /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
686382D32ABE173000E27AAD /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
686382D82ABE173000E27AAD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
686382D92ABE173000E27AAD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
686382DB2ABE173000E27AAD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = FlutterAppExtensionTestHost/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.FlutterAppExtensionTestHost;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
686382DC2ABE173000E27AAD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = FlutterAppExtensionTestHost/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.FlutterAppExtensionTestHost;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
686382BC2ABE172F00E27AAD /* Build configuration list for PBXProject "FlutterAppExtensionTestHost" */ = {
isa = XCConfigurationList;
buildConfigurations = (
686382D82ABE173000E27AAD /* Debug */,
686382D92ABE173000E27AAD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
686382DA2ABE173000E27AAD /* Build configuration list for PBXNativeTarget "FlutterAppExtensionTestHost" */ = {
isa = XCConfigurationList;
buildConfigurations = (
686382DB2ABE173000E27AAD /* Debug */,
686382DC2ABE173000E27AAD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 686382B92ABE172F00E27AAD /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,9 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@end

View File

@ -0,0 +1,38 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
// Override point for customization after application launch.
return YES;
}
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration*)application:(UIApplication*)application
configurationForConnectingSceneSession:(UISceneSession*)connectingSceneSession
options:(UISceneConnectionOptions*)options {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration"
sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication*)application
didDiscardSceneSessions:(NSSet<UISceneSession*>*)sceneSessions {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called
// shortly after application:didFinishLaunchingWithOptions. Use this method to release any
// resources that were specific to the discarded scenes, as they will not return.
}
@end

View File

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,11 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property(strong, nonatomic) UIWindow* window;
@end

View File

@ -0,0 +1,52 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "SceneDelegate.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene*)scene
willConnectToSession:(UISceneSession*)session
options:(UISceneConnectionOptions*)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided
// UIWindowScene `scene`. If using a storyboard, the `window` property will automatically be
// initialized and attached to the scene. This delegate does not imply the connecting scene or
// session are new (see `application:configurationForConnectingSceneSession` instead).
}
- (void)sceneDidDisconnect:(UIScene*)scene {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene
// connects. The scene may re-connect later, as its session was not necessarily discarded (see
// `application:didDiscardSceneSessions` instead).
}
- (void)sceneDidBecomeActive:(UIScene*)scene {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was
// inactive.
}
- (void)sceneWillResignActive:(UIScene*)scene {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
- (void)sceneWillEnterForeground:(UIScene*)scene {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
- (void)sceneDidEnterBackground:(UIScene*)scene {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state
// information to restore the scene back to its current state.
}
@end

View File

@ -0,0 +1,9 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

View File

@ -0,0 +1,33 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton* openShare =
[UIButton systemButtonWithPrimaryAction:[UIAction actionWithHandler:^(
__kindof UIAction* _Nonnull action) {
UIActivityViewController* activityVC =
[[UIActivityViewController alloc] initWithActivityItems:@[ @"text to share" ]
applicationActivities:nil];
activityVC.excludedActivityTypes = @[
UIActivityTypePrint, UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll
]; // Exclude whichever aren't relevant
[self presentViewController:activityVC animated:YES completion:nil];
}]];
openShare.backgroundColor = [UIColor systemPinkColor];
[openShare setTitle:@"Open Share" forState:UIControlStateNormal];
[self.view addSubview:openShare];
openShare.frame = CGRectMake(0, 0, 200, 200);
}
@end

View File

@ -0,0 +1,15 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
NSString* appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

View File

@ -0,0 +1,29 @@
<!--Dummy plist file to make the impeller version of scenario test happy-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--This flag does not do anything, it only makes the xcodebuild command happy-->
<key>FLTEnableImpeller</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "container:Scenarios/Scenarios.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -62,6 +62,12 @@
6860CE252A01B2FF00B68EC5 /* golden_two_platform_view_clip_rrect_iPhone SE (3rd generation)_16.2_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6860CE222A01B2FF00B68EC5 /* golden_two_platform_view_clip_rrect_iPhone SE (3rd generation)_16.2_simulator.png */; };
6860CE262A01B2FF00B68EC5 /* golden_two_platform_view_clip_rect_iPhone SE (3rd generation)_16.2_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6860CE232A01B2FF00B68EC5 /* golden_two_platform_view_clip_rect_iPhone SE (3rd generation)_16.2_simulator.png */; };
6860CE272A01B2FF00B68EC5 /* golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6860CE242A01B2FF00B68EC5 /* golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png */; };
686382EC2AC1F9F300E27AAD /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 686382EB2AC1F9F300E27AAD /* ShareViewController.m */; };
686382EF2AC1F9F300E27AAD /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 686382ED2AC1F9F300E27AAD /* MainInterface.storyboard */; };
686382F32AC1F9F300E27AAD /* ScenariosShare.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 686382E82AC1F9F300E27AAD /* ScenariosShare.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
686383132AC202B700E27AAD /* AppExtensionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 686383122AC202B700E27AAD /* AppExtensionTests.m */; };
686383152AC2175100E27AAD /* ../../Flutter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* ../../Flutter.xcframework */; };
686383162AC2175100E27AAD /* ../../Flutter.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* ../../Flutter.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
68A5B63423EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A5B63323EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m */; };
68D4017D2564859300ECD91A /* ContinuousTexture.m in Sources */ = {isa = PBXBuildFile; fileRef = 68D4017C2564859300ECD91A /* ContinuousTexture.m */; };
68D93AEE2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 68D93AED2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png */; };
@ -83,6 +89,27 @@
remoteGlobalIDString = 248D76C622E388370012F0C1;
remoteInfo = Scenarios;
};
686382F12AC1F9F300E27AAD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 248D76BF22E388370012F0C1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 686382E72AC1F9F300E27AAD;
remoteInfo = ScenariosShare;
};
6863830A2AC2024200E27AAD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 686383052AC2024200E27AAD /* FlutterAppExtensionTestHost.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 686382C12ABE172F00E27AAD;
remoteInfo = FlutterAppExtensionTestHost;
};
686383102AC2027100E27AAD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 686383052AC2024200E27AAD /* FlutterAppExtensionTestHost.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 686382C02ABE172F00E27AAD;
remoteInfo = FlutterAppExtensionTestHost;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@ -120,6 +147,28 @@
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
686382F42AC1F9F300E27AAD /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
686382F32AC1F9F300E27AAD /* ScenariosShare.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
686383172AC2175100E27AAD /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
686383162AC2175100E27AAD /* ../../Flutter.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@ -185,6 +234,13 @@
6860CE222A01B2FF00B68EC5 /* golden_two_platform_view_clip_rrect_iPhone SE (3rd generation)_16.2_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_two_platform_view_clip_rrect_iPhone SE (3rd generation)_16.2_simulator.png"; sourceTree = "<group>"; };
6860CE232A01B2FF00B68EC5 /* golden_two_platform_view_clip_rect_iPhone SE (3rd generation)_16.2_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_two_platform_view_clip_rect_iPhone SE (3rd generation)_16.2_simulator.png"; sourceTree = "<group>"; };
6860CE242A01B2FF00B68EC5 /* golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png"; sourceTree = "<group>"; };
686382E82AC1F9F300E27AAD /* ScenariosShare.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ScenariosShare.appex; sourceTree = BUILT_PRODUCTS_DIR; };
686382EA2AC1F9F300E27AAD /* ShareViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareViewController.h; sourceTree = "<group>"; };
686382EB2AC1F9F300E27AAD /* ShareViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ShareViewController.m; sourceTree = "<group>"; };
686382EE2AC1F9F300E27AAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
686382F02AC1F9F300E27AAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
686383052AC2024200E27AAD /* FlutterAppExtensionTestHost.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FlutterAppExtensionTestHost.xcodeproj; path = ../FlutterAppExtensionTestHost/FlutterAppExtensionTestHost.xcodeproj; sourceTree = "<group>"; };
686383122AC202B700E27AAD /* AppExtensionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppExtensionTests.m; sourceTree = "<group>"; };
68A5B63323EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlatformViewGestureRecognizerTests.m; sourceTree = "<group>"; };
68D4017B2564859300ECD91A /* ContinuousTexture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContinuousTexture.h; sourceTree = "<group>"; };
68D4017C2564859300ECD91A /* ContinuousTexture.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ContinuousTexture.m; sourceTree = "<group>"; };
@ -219,15 +275,25 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
686382E52AC1F9F300E27AAD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
686383152AC2175100E27AAD /* ../../Flutter.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
248D76BE22E388370012F0C1 = {
isa = PBXGroup;
children = (
686383052AC2024200E27AAD /* FlutterAppExtensionTestHost.xcodeproj */,
248D76C922E388370012F0C1 /* Scenarios */,
248D76E222E388380012F0C1 /* ScenariosTests */,
248D76ED22E388380012F0C1 /* ScenariosUITests */,
686382E92AC1F9F300E27AAD /* ScenariosShare */,
248D76C822E388370012F0C1 /* Products */,
248D76FC22E388900012F0C1 /* Frameworks */,
);
@ -239,6 +305,7 @@
248D76C722E388370012F0C1 /* Scenarios.app */,
248D76DF22E388380012F0C1 /* ScenariosTests.xctest */,
248D76EA22E388380012F0C1 /* ScenariosUITests.xctest */,
686382E82AC1F9F300E27AAD /* ScenariosShare.appex */,
);
name = Products;
sourceTree = "<group>";
@ -298,6 +365,7 @@
246A6610252E693A00EAB0F3 /* RenderingSelectionTest.m */,
0DDEBC88258830B40065D0E8 /* SpawnEngineTest.m */,
F26F15B7268B6B5500EC54D3 /* iPadGestureTests.m */,
686383122AC202B700E27AAD /* AppExtensionTests.m */,
);
path = ScenariosUITests;
sourceTree = "<group>";
@ -311,6 +379,25 @@
name = Frameworks;
sourceTree = "<group>";
};
686382E92AC1F9F300E27AAD /* ScenariosShare */ = {
isa = PBXGroup;
children = (
686382EA2AC1F9F300E27AAD /* ShareViewController.h */,
686382EB2AC1F9F300E27AAD /* ShareViewController.m */,
686382ED2AC1F9F300E27AAD /* MainInterface.storyboard */,
686382F02AC1F9F300E27AAD /* Info.plist */,
);
path = ScenariosShare;
sourceTree = "<group>";
};
686383062AC2024200E27AAD /* Products */ = {
isa = PBXGroup;
children = (
6863830B2AC2024200E27AAD /* FlutterAppExtensionTestHost.app */,
);
name = Products;
sourceTree = "<group>";
};
F7B464DC2759D02B00079189 /* Goldens */ = {
isa = PBXGroup;
children = (
@ -355,10 +442,12 @@
248D76C422E388370012F0C1 /* Frameworks */,
248D76C522E388370012F0C1 /* Resources */,
246B4E4422E3B5F700073EBF /* Embed Frameworks */,
686382F42AC1F9F300E27AAD /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
686382F22AC1F9F300E27AAD /* PBXTargetDependency */,
);
name = Scenarios;
productName = Scenarios;
@ -396,6 +485,7 @@
buildRules = (
);
dependencies = (
686383112AC2027100E27AAD /* PBXTargetDependency */,
248D76EC22E388380012F0C1 /* PBXTargetDependency */,
);
name = ScenariosUITests;
@ -403,6 +493,24 @@
productReference = 248D76EA22E388380012F0C1 /* ScenariosUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
686382E72AC1F9F300E27AAD /* ScenariosShare */ = {
isa = PBXNativeTarget;
buildConfigurationList = 686382F72AC1F9F300E27AAD /* Build configuration list for PBXNativeTarget "ScenariosShare" */;
buildPhases = (
686382E42AC1F9F300E27AAD /* Sources */,
686382E52AC1F9F300E27AAD /* Frameworks */,
686382E62AC1F9F300E27AAD /* Resources */,
686383172AC2175100E27AAD /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = ScenariosShare;
productName = ScenariosShare;
productReference = 686382E82AC1F9F300E27AAD /* ScenariosShare.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -426,6 +534,9 @@
LastSwiftMigration = 1030;
TestTargetID = 248D76C622E388370012F0C1;
};
686382E72AC1F9F300E27AAD = {
CreatedOnToolsVersion = 15.0;
};
};
};
buildConfigurationList = 248D76C222E388370012F0C1 /* Build configuration list for PBXProject "Scenarios" */;
@ -439,15 +550,32 @@
mainGroup = 248D76BE22E388370012F0C1;
productRefGroup = 248D76C822E388370012F0C1 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 686383062AC2024200E27AAD /* Products */;
ProjectRef = 686383052AC2024200E27AAD /* FlutterAppExtensionTestHost.xcodeproj */;
},
);
projectRoot = "";
targets = (
248D76C622E388370012F0C1 /* Scenarios */,
248D76DE22E388380012F0C1 /* ScenariosTests */,
248D76E922E388380012F0C1 /* ScenariosUITests */,
686382E72AC1F9F300E27AAD /* ScenariosShare */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
6863830B2AC2024200E27AAD /* FlutterAppExtensionTestHost.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = FlutterAppExtensionTestHost.app;
remoteRef = 6863830A2AC2024200E27AAD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
248D76C522E388370012F0C1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
@ -497,6 +625,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
686382E62AC1F9F300E27AAD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
686382EF2AC1F9F300E27AAD /* MainInterface.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -539,10 +675,19 @@
F26F15B8268B6B5600EC54D3 /* iPadGestureTests.m in Sources */,
246A6611252E693A00EAB0F3 /* RenderingSelectionTest.m in Sources */,
4F06F1B32473296E000AF246 /* LocalizationInitializationTest.m in Sources */,
686383132AC202B700E27AAD /* AppExtensionTests.m in Sources */,
0DDEBC89258830B40065D0E8 /* SpawnEngineTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
686382E42AC1F9F300E27AAD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
686382EC2AC1F9F300E27AAD /* ShareViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -556,8 +701,29 @@
target = 248D76C622E388370012F0C1 /* Scenarios */;
targetProxy = 248D76EB22E388380012F0C1 /* PBXContainerItemProxy */;
};
686382F22AC1F9F300E27AAD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 686382E72AC1F9F300E27AAD /* ScenariosShare */;
targetProxy = 686382F12AC1F9F300E27AAD /* PBXContainerItemProxy */;
};
686383112AC2027100E27AAD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = FlutterAppExtensionTestHost;
targetProxy = 686383102AC2027100E27AAD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
686382ED2AC1F9F300E27AAD /* MainInterface.storyboard */ = {
isa = PBXVariantGroup;
children = (
686382EE2AC1F9F300E27AAD /* Base */,
);
name = MainInterface.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
248D76F122E388380012F0C1 /* Debug */ = {
isa = XCBuildConfiguration;
@ -678,7 +844,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@ -701,7 +867,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@ -723,7 +889,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@ -750,7 +916,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@ -776,7 +942,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@ -802,7 +968,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = S8QB4VV633;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@ -824,6 +990,70 @@
};
name = Release;
};
686382F52AC1F9F300E27AAD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ScenariosShare/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ScenariosShare;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 flutter. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.Scenarios.ScenariosShare;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
686382F62AC1F9F300E27AAD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ScenariosShare/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ScenariosShare;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 flutter. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.Scenarios.ScenariosShare;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -863,6 +1093,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
686382F72AC1F9F300E27AAD /* Build configuration list for PBXNativeTarget "ScenariosShare" */ = {
isa = XCConfigurationList;
buildConfigurations = (
686382F52AC1F9F300E27AAD /* Debug */,
686382F62AC1F9F300E27AAD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 248D76BF22E388370012F0C1 /* Project object */;

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Share View Controller-->
<scene sceneID="ceB-am-kn3">
<objects>
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="" sceneMemberID="viewController">
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<string>TRUEPREDICATE</string>
</dict>
<key>NSExtensionPrincipalClass</key>
<string>ShareViewController</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface ShareViewController : FlutterViewController
@end

View File

@ -0,0 +1,31 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ShareViewController.h"
@interface ShareViewController ()
@end
@implementation ShareViewController
- (instancetype)init {
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"FlutterControllerTest" project:nil];
[engine run];
self = [self initWithEngine:engine nibName:nil bundle:nil];
self.view.accessibilityIdentifier = @"flutter_view";
[engine.binaryMessenger
setMessageHandlerOnChannel:@"waiting_for_status"
binaryMessageHandler:^(NSData* _Nullable message, FlutterBinaryReply _Nonnull reply) {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"driver"
binaryMessenger:engine.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]];
[channel invokeMethod:@"set_scenario" arguments:@{@"name" : @"app_extension"}];
}];
return self;
}
@end

View File

@ -0,0 +1,58 @@
// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <XCTest/XCTest.h>
#import "GoldenTestManager.h"
@interface AppExtensionTests : XCTestCase
@property(nonatomic, strong) XCUIApplication* hostApplication;
@end
@implementation AppExtensionTests
- (void)setUp {
[super setUp];
self.continueAfterFailure = NO;
self.hostApplication =
[[XCUIApplication alloc] initWithBundleIdentifier:@"dev.flutter.FlutterAppExtensionTestHost"];
}
- (void)testAppExtensionLaunching {
[self.hostApplication launch];
XCUIElement* button = self.hostApplication.buttons[@"Open Share"];
if (![button waitForExistenceWithTimeout:10]) {
NSLog(@"%@", self.hostApplication.debugDescription);
XCTFail(@"Failed due to not able to find any button with %@ seconds", @(10));
}
[button tap];
BOOL launchedExtensionInFlutter = NO;
// Custom share extension button (like the one in this test) does not have a unique
// identity. They are all identified as `XCElementSnapshotPrivilegedValuePlaceholder`.
// Loop through all the `XCElementSnapshotPrivilegedValuePlaceholder` and find the Flutter one.
for (int i = 0; i < self.hostApplication.collectionViews.cells.count; i++) {
XCUIElement* shareSheetCell =
[self.hostApplication.collectionViews.cells elementBoundByIndex:i];
if (![shareSheetCell.label isEqualToString:@"XCElementSnapshotPrivilegedValuePlaceholder"]) {
continue;
}
[shareSheetCell tap];
XCUIElement* flutterView = self.hostApplication.otherElements[@"flutter_view"];
if ([flutterView waitForExistenceWithTimeout:10]) {
launchedExtensionInFlutter = YES;
break;
}
// All the built-in share extensions have a Cancel button.
// Tap the Cancel button to close the built-in extension.
XCUIElement* cancel = self.hostApplication.buttons[@"Cancel"];
if ([cancel waitForExistenceWithTimeout:10]) {
[cancel tap];
}
}
// App extension successfully launched flutter view.
XCTAssertTrue(launchedExtensionInFlutter);
}
@end

View File

@ -53,6 +53,7 @@ const double kDefaultRmseThreshold = 0.5;
@"--two-platform-view-clip-rect" : @"two_platform_view_clip_rect",
@"--two-platform-view-clip-rrect" : @"two_platform_view_clip_rrect",
@"--two-platform-view-clip-path" : @"two_platform_view_clip_path",
@"--app-extension" : @"app_extension",
};
});
_identifier = launchArgsMap[launchArg];

View File

@ -0,0 +1,44 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'scenario.dart';
/// Shows a text that is shown in app extension.
class DarwinAppExtensionScenario extends Scenario {
/// Creates the DarwinAppExtensionScenario scenario.
DarwinAppExtensionScenario(super.view);
// Semi-arbitrary.
final double _screenWidth = 700;
@override
void onBeginFrame(Duration duration) {
final SceneBuilder builder = SceneBuilder();
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
final ParagraphBuilder paragraphBuilder =
ParagraphBuilder(ParagraphStyle())
..pushStyle(TextStyle(fontSize: 80))
..addText('flutter Scenarios app extension.')
..pop();
final Paragraph paragraph = paragraphBuilder.build();
paragraph.layout(ParagraphConstraints(width: _screenWidth));
canvas.drawParagraph(paragraph, const Offset(50, 80));
final Picture picture = recorder.endRecording();
builder.addPicture(
Offset.zero,
picture,
willChangeHint: true,
);
final Scene scene = builder.build();
view.render(scene);
scene.dispose();
}
}

View File

@ -6,6 +6,7 @@ import 'dart:ui';
import 'animated_color_square.dart';
import 'bogus_font_text.dart';
import 'darwin_app_extension_scenario.dart';
import 'get_bitmap_scenario.dart';
import 'initial_route_reply.dart';
import 'locale_initialization.dart';
@ -66,6 +67,7 @@ Map<String, _ScenarioFactory> _scenarios = <String, _ScenarioFactory>{
'pointer_events': (FlutterView view) => TouchesScenario(view),
'display_texture': (FlutterView view) => DisplayTexture(view),
'get_bitmap': (FlutterView view) => GetBitmapScenario(view),
'app_extension': (FlutterView view) => DarwinAppExtensionScenario(view),
};
Map<String, dynamic> _currentScenarioParams = <String, dynamic>{};

View File

@ -109,7 +109,9 @@ if set -o pipefail && xcodebuild -sdk iphonesimulator \
-skip-testing ScenariosUITests/TwoPlatformViewClipRRectTests/testPlatformView \
-skip-testing ScenariosUITests/TwoPlatformViewsWithOtherBackDropFilterTests/testPlatformView \
-skip-testing ScenariosUITests/UnobstructedPlatformViewTests/testMultiplePlatformViewsWithOverlays \
INFOPLIST_FILE="Scenarios/Info_Impeller.plist"; then # Plist with FLTEnableImpeller=YES
# Plist with FLTEnableImpeller=YES, all projects in the workspace requires this file.
# For example, FlutterAppExtensionTestHost has a dummy file under the below directory.
INFOPLIST_FILE="Scenarios/Info_Impeller.plist"; then
echo "test success."
else
echo "test failed."