project init
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
assets/game
|
||||
.DS_Store
|
||||
/platform.js
|
244
doc/README_IOS.md
Normal file
@ -0,0 +1,244 @@
|
||||
# 项目发布设置使用说明
|
||||
|
||||
---
|
||||
|
||||
此文档旨在帮助用户顺利的完成项目打包发布,解决发布过程中可能遇到的问题,并最终完成发布工程的个性化配置和功能接入,文档分为以下几个部分:
|
||||
|
||||
> * 发布设置前的准备工作
|
||||
> * 项目发布配置
|
||||
> * 发布工程的个性化配置
|
||||
> * JS和原生的通信接入
|
||||
> * 运行时error事件和state事件处理方法
|
||||
> * 添加loading界面
|
||||
|
||||
---
|
||||
|
||||
## 发布设置前的准备工作
|
||||
|
||||
- 安装最新版本的launcher
|
||||
- 确认引擎版本
|
||||
- 下载的引擎版本必须为***5.1.6及以上***
|
||||
- 在launcher中的引擎页选择下载
|
||||
- 安装Xcode
|
||||
- 建议版本: 8.3或以上
|
||||
- 后续需要在Xcode中完成发布项目的修改和功能接入
|
||||
|
||||
---
|
||||
|
||||
## 项目发布配置
|
||||
|
||||
### 1. 创建项目
|
||||
|
||||
- launcher项目页中,点击创建项目,填入项目名称,并选择引擎版本为5.1.6(或以上),点击创建按钮。
|
||||
|
||||
>此文档不涉及具体项目功能,可以关闭 Egret Wing窗口。
|
||||
|
||||
### 2. 发布配置
|
||||
|
||||
- 在launcher的项目页中找到新创建的项目,点击该项目下的发布设置按钮。
|
||||

|
||||
- 点击左侧的iOS按钮,然后在右侧页面中,输入应用名称,填写新的应用包名,点击确定。
|
||||
- 新弹出的窗口中选择点击***打开文件夹***按钮。
|
||||
|
||||
---
|
||||
|
||||
## 发布工程的个性化配置
|
||||
|
||||
- 解决国行手机首次启动需要请求网络权限的问题
|
||||
- 模版中通过`[_native setNetworkStatusChangeCallback:]`监听网络状态,有网络连接时才启动游戏。
|
||||
|
||||
- 访问相册权限的问题
|
||||
- 为了支持保存截图到本地的功能,模版中默认注册了访问相册的权限,如不需要可以从info.plist中删除。
|
||||
- 模版中默认加入的权限并无对应的文字,若要发布至AppStore中,必须在权限后添加任意提醒用户的文字才能通过审核,如“允许Egret Native访问您的相册?”
|
||||
|
||||

|
||||
> - Privacy - Photo Library Usage Description是IOS11.0版本之前的相册读写权限
|
||||
> - Privacy - Photo Library Additions Usage Description是IOS11.0版本之后的相册写权限,读权限系统已经默认开放
|
||||
|
||||
- 没加文字之前与添加文字之后
|
||||
|
||||
 
|
||||
 
|
||||
|
||||
- 个性化设置
|
||||
- 修改游戏地址:将函数`[native startGame:]`的参数替换为当前游戏的地址。
|
||||
|
||||
>需要注意,如果工程的assets目录下存在game文件,那么此处填写的游戏必须和game文件中的游戏保持一致,否则会出现问题。
|
||||
|
||||
- 控制FPS面板的显示:修改`_native.config.showFPS = true/false;`。true为显示,false为隐藏。
|
||||
- 控制log在屏幕上的显示时间:修改`_native.config.fpsLogTime = 30;`,改为`-1`时是永久显示。
|
||||
- 是否禁用核心渲染驱动:修改`_native.config.disableNativeRender = false/true`。false为启用核心渲染驱动,true为禁用核心渲染驱动。
|
||||
- 是否清理缓存:修改`_native.config.clearCache = false/true;`。false为不自动清理缓存,true为自动清理缓存。
|
||||
- 控制页面超时时间:修改`_native.config.loadingTimeout = 0;`。单位为秒,0为不设置超时。
|
||||
- 游戏是否支持刘海屏显示:修改`_native.config.useCutout = false;`。true 为游戏支持并适配,false为不支持。
|
||||
|
||||
---
|
||||
|
||||
## JS和原生的通信接入
|
||||
|
||||
### 1. 原生部分
|
||||
- 在AppDelegate.mm的`setExternalInterfaces`方法里配置通信接口
|
||||
- `[_native setExternalInterface: Callback:]` 注册JS中可以调用的原生函数
|
||||
- `[_native callExternalInterface: Value:]`调用JS函数
|
||||
- `setExternalInterface`方法的第一个参数是JS中调用原生函数的函数名,第二个参数是该原生函数的功能实现
|
||||
- `callExternalInterface`方法的第一个参数是JS函数的函数名,第二个传入的参数
|
||||
|
||||
```objective-c
|
||||
- (void)setExternalInterfaces {
|
||||
__block EgretNativeIOS* support = _native;
|
||||
[_native setExternalInterface:@"sendToNative" Callback:^(NSString* message) {
|
||||
NSString* str = @"Native get message: ";
|
||||
str = [str stringByAppendingString:message];
|
||||
NSLog(@"%@", str);
|
||||
[support callExternalInterface:@"sendToJS" Value:str];
|
||||
}];
|
||||
}
|
||||
```
|
||||
|
||||
### 2. JS部分
|
||||
|
||||
- `egret.ExternalInterface.call`调用注册过的原生函数
|
||||
|
||||
```js
|
||||
egret.ExternalInterface.call("sendToNative", "message from JS");
|
||||
```
|
||||
|
||||
- `egret.ExternalInterface.addCallback`注册原生中可以调用的JS函数
|
||||
|
||||
```js
|
||||
function sendToJS(msg) {
|
||||
console.log(msg);
|
||||
}
|
||||
egret.ExternalInterface.addCallback("sendToJS", sendToJS);
|
||||
```
|
||||
|
||||
> 只有通过`setExternalInterface`注册的原生函数,才能在JS中通过`call`调用。
|
||||
> 只有通过`addCallback`注册的JS函数,才能在原生中通过`callExternalInterface`调用。
|
||||
|
||||
---
|
||||
|
||||
## runtime阶段状态定义
|
||||
|
||||
- 我们将runtime启动及运行的阶段进行了定义,主要分为如下几种阶段状态:
|
||||
|
||||
> * loading: 系统初始时的默认状态
|
||||
> * starting: 表示index.html已经加载成功
|
||||
> * running: 表示starting状态后,执行完json、js等文件资源加载并开始执行渲染
|
||||
|
||||
## 运行时state事件处理方法
|
||||
|
||||
### 1. runtime运行中各个事件的说明
|
||||
- 事件说明如下
|
||||
|
||||
|事件类型 |事件消息 |所属阶段 |事件意义 |
|
||||
|:-------------|----------------------------|:-----------------|:-----------------------------------------------------------------------------------------|
|
||||
|@onState |{"state”:”starting”} |loading到starting |index.html加载成功 |
|
||||
|@onState |{"state”:”running”} |starting到running |starting状态后开始执行渲染(注:starting状态后,若json或js等文件加载失败,会通过具体的js错误进行提示) |
|
||||
|
||||
### 2. 监听state事件的方法
|
||||
|
||||
- 注册对state事件的监听,在函数`setExternalInterfaces`中:
|
||||
|
||||
```objective-c
|
||||
- (void)setExternalInterfaces {
|
||||
__block EgretNativeIOS* support = _native;
|
||||
__block AppDelegate* thiz = self;
|
||||
|
||||
[_native setExternalInterface:@"@onState" Callback:^(NSString* message) {
|
||||
NSData* jsonData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError* err;
|
||||
NSDictionary* dic = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:NSJSONReadingMutableContainers
|
||||
error:&err];
|
||||
if (err) {
|
||||
NSLog(@"onState message failed to analyze");
|
||||
return;
|
||||
}
|
||||
|
||||
NSString* state = [dic objectForKey:@"state"];
|
||||
if ([state isEqualToString:@"starting"]) {// 正在启动引擎
|
||||
NSLog(@"Engine starting");
|
||||
} else if ([state isEqualToString:@"running"]) {// 引擎开始渲染
|
||||
// 如果您使用了自定义闪屏,这里是关掉的好时机
|
||||
NSLog(@"Engine is rendering");
|
||||
}
|
||||
NSLog(@"Native get onState message: %@", state);
|
||||
}];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 处理错误
|
||||
|
||||
如果您需要处理错误,请参照 [Egret Native 上处理游戏错误](https://docs.egret.com/native/docs/manual/abouterrors)。
|
||||
|
||||
---
|
||||
|
||||
## 添加loading界面
|
||||
|
||||
>loading界面的使用依赖与state事件的处理,请先完成上一部分的阅读。
|
||||
|
||||
### 1. 打开loading界面
|
||||
|
||||
- 在AppDelegate的didFinishLaunchingWithOptions函数中调用函数showLoadingView
|
||||
|
||||
```objective-c
|
||||
@implementation AppDelegate {
|
||||
UIViewController* _viewController;
|
||||
UIImageView* _imageView;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
NSString* gameUrl = @"http://tool.egret-labs.org/Weiduan/game/index.html";
|
||||
|
||||
_native = [[EgretNativeIOS alloc] init];
|
||||
_native.config.showFPS = true;
|
||||
_native.config.fpsLogTime = 30;
|
||||
_native.config.disableNativeRender = false;
|
||||
_native.config.clearCache = false;
|
||||
|
||||
_viewController = [[ViewController alloc] initWithEAGLView:[_native createEAGLView]];
|
||||
if (![_native initWithViewController:_viewController]) {
|
||||
return false;
|
||||
}
|
||||
[self setExternalInterfaces];
|
||||
|
||||
NSString* networkState = [_native getNetworkState];
|
||||
if ([networkState isEqualToString:@"NotReachable"]) {
|
||||
__block EgretNativeIOS* native = _native;
|
||||
[_native setNetworkStatusChangeCallback:^(NSString* state) {
|
||||
if (![state isEqualToString:@"NotReachable"]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[native startGame:gameUrl];
|
||||
});
|
||||
}
|
||||
}];
|
||||
return true;
|
||||
}
|
||||
|
||||
[_native startGame:gameUrl];
|
||||
|
||||
[self showLoadingView];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)showLoadingView {
|
||||
_imageView = [[UIImageView alloc] initWithFrame:_viewController.view.frame];
|
||||
[_imageView setImage:[UIImage imageNamed:@"icon"]];
|
||||
[_viewController.view addSubview:_imageView];
|
||||
[_viewController.view bringSubviewToFront:_imageView];
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 关闭loading界面
|
||||
|
||||
- 收到{"state”:”running”}消息后,调用函数hideLoadingView
|
||||
|
||||
```objective-c
|
||||
- (void)hideLoadingView {
|
||||
[_imageView removeFromSuperview];
|
||||
}
|
||||
```
|
BIN
doc/images/PhotoAdditionPrivacy.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
doc/images/PhotoAdditionPrivacyWithString.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
doc/images/PhotoAlbumPrivacy.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
doc/images/PhotoAlbumPrivacyWithString.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
doc/images/info-plist.jpg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
doc/images/publish_btn.png
Normal file
After Width: | Height: | Size: 25 KiB |
45
egret-libs/include/EgretNativeIOS.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (C) Egret Technology. All rights reserved.
|
||||
// EgretRuntimeVersion: 1.1.2
|
||||
// EgretRuntimeBuild: 24082931
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface EgretNativeConfig : NSObject
|
||||
|
||||
@property (nonatomic) bool showFPS;
|
||||
@property (nonatomic) int fpsLogTime;
|
||||
@property (nonatomic) bool disableNativeRender;
|
||||
@property (nonatomic) bool enableGLBatch;
|
||||
@property (nonatomic) bool clearCache;
|
||||
@property (nonatomic) unsigned long loadingTimeout;
|
||||
@property (nonatomic) bool transparentGameView;
|
||||
@property (nonatomic) NSString* preloadPath;
|
||||
@property (nonatomic) bool useCutout;
|
||||
|
||||
@end
|
||||
|
||||
@interface EgretNativeIOS : NSObject
|
||||
|
||||
- (instancetype)init;
|
||||
- (UIView*)createEAGLView;
|
||||
- (bool)initWithViewController:(UIViewController*)viewController;
|
||||
- (UIViewController*)getRootViewController;
|
||||
- (NSString*)getRuntimeVersion;
|
||||
- (void)setOption:(NSString*)value forKey:(NSString*)key;
|
||||
- (void)startGame:(NSString*)gameUrl;
|
||||
- (void)pause;
|
||||
- (void)resume;
|
||||
|
||||
- (void)setExternalInterface:(NSString*)funcName Callback:(void(^)(NSString*))callback;
|
||||
- (void)callExternalInterface:(NSString*)funcName Value:(NSString*)value;
|
||||
|
||||
- (void)setFPSBoardEnable:(bool)enable;
|
||||
|
||||
- (NSString*)getNetworkState;
|
||||
- (void)setNetworkStatusChangeCallback:(void(^)(NSString*))callback;
|
||||
|
||||
- (void)destroy;
|
||||
|
||||
@property (nonatomic, strong) UIWindow* window;
|
||||
@property (nonatomic, readonly, strong) EgretNativeConfig* config;
|
||||
|
||||
@end
|
BIN
egret-libs/libEgretNativeIOS.a
Normal file
503
ios-template.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,503 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
305DF7A3200D95C5008022B6 /* game in Resources */ = {isa = PBXBuildFile; fileRef = 305DF7A2200D95C5008022B6 /* game */; };
|
||||
306A7A98200C83F500E1EBB6 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 306A7A97200C83F500E1EBB6 /* ViewController.mm */; };
|
||||
306A7A9D200C83F500E1EBB6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 306A7A9C200C83F500E1EBB6 /* Assets.xcassets */; };
|
||||
306A7AAB200C88E500E1EBB6 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AAA200C88E500E1EBB6 /* AVFoundation.framework */; };
|
||||
306A7AAD200C88EA00E1EBB6 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AAC200C88EA00E1EBB6 /* AudioToolbox.framework */; };
|
||||
306A7AAF200C88F600E1EBB6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AAE200C88F600E1EBB6 /* Foundation.framework */; };
|
||||
306A7AB1200C890300E1EBB6 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AB0200C890300E1EBB6 /* OpenAL.framework */; };
|
||||
306A7AB3200C890E00E1EBB6 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AB2200C890E00E1EBB6 /* SystemConfiguration.framework */; };
|
||||
306A7AB5200C891B00E1EBB6 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AB4200C891B00E1EBB6 /* libz.tbd */; };
|
||||
306A7AB7200C892500E1EBB6 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7AB6200C892500E1EBB6 /* libiconv.tbd */; };
|
||||
306A7ABB200C898400E1EBB6 /* libicucore.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7ABA200C898400E1EBB6 /* libicucore.tbd */; };
|
||||
306A7ABD200C89B900E1EBB6 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7ABC200C89B900E1EBB6 /* JavaScriptCore.framework */; };
|
||||
306A7ABF200C89C000E1EBB6 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 306A7ABE200C89C000E1EBB6 /* OpenGLES.framework */; };
|
||||
3077067820215DF200548664 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3077067720215DF200548664 /* MediaPlayer.framework */; };
|
||||
3077067A20215DF600548664 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3077067920215DF600548664 /* libsqlite3.tbd */; };
|
||||
307B49CF2059046B003D64E0 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 307B49CE2059046B003D64E0 /* AdSupport.framework */; };
|
||||
30E559EA200F1DE2001C0B78 /* libEgretNativeIOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 30E559E9200F1DE2001C0B78 /* libEgretNativeIOS.a */; };
|
||||
B34149E425F23387008BDFF8 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B34149E325F23387008BDFF8 /* CoreMotion.framework */; };
|
||||
B34149E625F23392008BDFF8 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B34149E525F23392008BDFF8 /* CoreLocation.framework */; };
|
||||
D5FF442F26A80E5F00CF155C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FF442E26A80E5F00CF155C /* AppDelegate.swift */; };
|
||||
D5FF443126A80F8600CF155C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FF443026A80F8600CF155C /* ViewController.swift */; };
|
||||
D5FF443326A80FA600CF155C /* m_loading.jpg in Resources */ = {isa = PBXBuildFile; fileRef = D5FF443226A80FA600CF155C /* m_loading.jpg */; };
|
||||
D5FF444E26A80FF600CF155C /* IDUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FF444D26A80FF600CF155C /* IDUtil.swift */; };
|
||||
D5FF445026A80FFB00CF155C /* KeychainPasswordItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FF444F26A80FFB00CF155C /* KeychainPasswordItem.swift */; };
|
||||
D5FF445426A948F600CF155C /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5FF445326A948F500CF155C /* StoreKit.framework */; };
|
||||
D5FF445726A94B8500CF155C /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = D5FF445626A94B8500CF155C /* SwiftyJSON */; };
|
||||
ED50D6502436EB69005B9E1E /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED50D64F2436EB69005B9E1E /* CoreMedia.framework */; };
|
||||
ED50D6522436EB70005B9E1E /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED50D6512436EB70005B9E1E /* AVKit.framework */; };
|
||||
ED9FBC2E21830D2A005A5DF0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED9FBC2D21830D2A005A5DF0 /* UIKit.framework */; };
|
||||
ED9FBC3021830D50005A5DF0 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED9FBC2F21830D50005A5DF0 /* CoreText.framework */; };
|
||||
ED9FBC3221830D63005A5DF0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED9FBC3121830D63005A5DF0 /* CoreGraphics.framework */; };
|
||||
EDF3B7E524580A4B009DFBBD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EDF3B7E424580A4B009DFBBD /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
305DF7A2200D95C5008022B6 /* game */ = {isa = PBXFileReference; lastKnownFileType = folder; name = game; path = assets/game; sourceTree = "<group>"; };
|
||||
306A7A8D200C83F500E1EBB6 /* 武极天下.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "武极天下.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
306A7A96200C83F500E1EBB6 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
306A7A97200C83F500E1EBB6 /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = "<group>"; };
|
||||
306A7A9C200C83F500E1EBB6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
306A7AA1200C83F500E1EBB6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
306A7AAA200C88E500E1EBB6 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
|
||||
306A7AAC200C88EA00E1EBB6 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
306A7AAE200C88F600E1EBB6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
306A7AB0200C890300E1EBB6 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
|
||||
306A7AB2200C890E00E1EBB6 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
306A7AB4200C891B00E1EBB6 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
306A7AB6200C892500E1EBB6 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
|
||||
306A7AB8200C896F00E1EBB6 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
||||
306A7ABA200C898400E1EBB6 /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; };
|
||||
306A7ABC200C89B900E1EBB6 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
306A7ABE200C89C000E1EBB6 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
|
||||
3077067720215DF200548664 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
|
||||
3077067920215DF600548664 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
|
||||
307B49CE2059046B003D64E0 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; };
|
||||
30E559E9200F1DE2001C0B78 /* libEgretNativeIOS.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libEgretNativeIOS.a; path = "egret-libs/libEgretNativeIOS.a"; sourceTree = "<group>"; };
|
||||
84860E512179DA92001FCEE7 /* README_IOS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README_IOS.md; sourceTree = "<group>"; };
|
||||
B34149E325F23387008BDFF8 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
|
||||
B34149E525F23392008BDFF8 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
|
||||
D5FF442D26A80E5E00CF155C /* wjtx-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "wjtx-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
D5FF442E26A80E5F00CF155C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
D5FF443026A80F8600CF155C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
D5FF443226A80FA600CF155C /* m_loading.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = m_loading.jpg; sourceTree = "<group>"; };
|
||||
D5FF444D26A80FF600CF155C /* IDUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IDUtil.swift; sourceTree = "<group>"; };
|
||||
D5FF444F26A80FFB00CF155C /* KeychainPasswordItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainPasswordItem.swift; sourceTree = "<group>"; };
|
||||
D5FF445226A832BE00CF155C /* 武极天下.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "武极天下.entitlements"; path = "../武极天下.entitlements"; sourceTree = "<group>"; };
|
||||
D5FF445326A948F500CF155C /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||
ED50D64F2436EB69005B9E1E /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
|
||||
ED50D6512436EB70005B9E1E /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = System/Library/Frameworks/AVKit.framework; sourceTree = SDKROOT; };
|
||||
ED9FBC2D21830D2A005A5DF0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
ED9FBC2F21830D50005A5DF0 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
|
||||
ED9FBC3121830D63005A5DF0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
EDF3B7E424580A4B009DFBBD /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
306A7A8A200C83F500E1EBB6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B34149E625F23392008BDFF8 /* CoreLocation.framework in Frameworks */,
|
||||
B34149E425F23387008BDFF8 /* CoreMotion.framework in Frameworks */,
|
||||
D5FF445726A94B8500CF155C /* SwiftyJSON in Frameworks */,
|
||||
ED9FBC3221830D63005A5DF0 /* CoreGraphics.framework in Frameworks */,
|
||||
ED9FBC3021830D50005A5DF0 /* CoreText.framework in Frameworks */,
|
||||
ED9FBC2E21830D2A005A5DF0 /* UIKit.framework in Frameworks */,
|
||||
307B49CF2059046B003D64E0 /* AdSupport.framework in Frameworks */,
|
||||
30E559EA200F1DE2001C0B78 /* libEgretNativeIOS.a in Frameworks */,
|
||||
3077067A20215DF600548664 /* libsqlite3.tbd in Frameworks */,
|
||||
3077067820215DF200548664 /* MediaPlayer.framework in Frameworks */,
|
||||
306A7ABF200C89C000E1EBB6 /* OpenGLES.framework in Frameworks */,
|
||||
306A7ABD200C89B900E1EBB6 /* JavaScriptCore.framework in Frameworks */,
|
||||
306A7ABB200C898400E1EBB6 /* libicucore.tbd in Frameworks */,
|
||||
306A7AB7200C892500E1EBB6 /* libiconv.tbd in Frameworks */,
|
||||
306A7AB5200C891B00E1EBB6 /* libz.tbd in Frameworks */,
|
||||
ED50D6502436EB69005B9E1E /* CoreMedia.framework in Frameworks */,
|
||||
ED50D6522436EB70005B9E1E /* AVKit.framework in Frameworks */,
|
||||
306A7AB3200C890E00E1EBB6 /* SystemConfiguration.framework in Frameworks */,
|
||||
306A7AAF200C88F600E1EBB6 /* Foundation.framework in Frameworks */,
|
||||
306A7AB1200C890300E1EBB6 /* OpenAL.framework in Frameworks */,
|
||||
306A7AAD200C88EA00E1EBB6 /* AudioToolbox.framework in Frameworks */,
|
||||
306A7AAB200C88E500E1EBB6 /* AVFoundation.framework in Frameworks */,
|
||||
D5FF445426A948F600CF155C /* StoreKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
305DF7A1200D957D008022B6 /* assets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
305DF7A2200D95C5008022B6 /* game */,
|
||||
);
|
||||
name = assets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
306A7A84200C83F500E1EBB6 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84860E502179DA92001FCEE7 /* doc */,
|
||||
305DF7A1200D957D008022B6 /* assets */,
|
||||
306A7A8F200C83F500E1EBB6 /* ios-template */,
|
||||
306A7A8E200C83F500E1EBB6 /* Products */,
|
||||
306A7AA7200C88C500E1EBB6 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
306A7A8E200C83F500E1EBB6 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
306A7A8D200C83F500E1EBB6 /* 武极天下.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
306A7A8F200C83F500E1EBB6 /* ios-template */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D5FF445226A832BE00CF155C /* 武极天下.entitlements */,
|
||||
EDF3B7E424580A4B009DFBBD /* LaunchScreen.storyboard */,
|
||||
D5FF444D26A80FF600CF155C /* IDUtil.swift */,
|
||||
D5FF444F26A80FFB00CF155C /* KeychainPasswordItem.swift */,
|
||||
D5FF442E26A80E5F00CF155C /* AppDelegate.swift */,
|
||||
306A7A96200C83F500E1EBB6 /* ViewController.h */,
|
||||
D5FF443026A80F8600CF155C /* ViewController.swift */,
|
||||
306A7A97200C83F500E1EBB6 /* ViewController.mm */,
|
||||
D5FF443226A80FA600CF155C /* m_loading.jpg */,
|
||||
306A7A9C200C83F500E1EBB6 /* Assets.xcassets */,
|
||||
306A7AA1200C83F500E1EBB6 /* Info.plist */,
|
||||
306A7A90200C83F500E1EBB6 /* Supporting Files */,
|
||||
D5FF442D26A80E5E00CF155C /* wjtx-Bridging-Header.h */,
|
||||
);
|
||||
path = "ios-template";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
306A7A90200C83F500E1EBB6 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
306A7AA7200C88C500E1EBB6 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D5FF445326A948F500CF155C /* StoreKit.framework */,
|
||||
B34149E525F23392008BDFF8 /* CoreLocation.framework */,
|
||||
B34149E325F23387008BDFF8 /* CoreMotion.framework */,
|
||||
ED50D6512436EB70005B9E1E /* AVKit.framework */,
|
||||
ED50D64F2436EB69005B9E1E /* CoreMedia.framework */,
|
||||
ED9FBC3121830D63005A5DF0 /* CoreGraphics.framework */,
|
||||
ED9FBC2F21830D50005A5DF0 /* CoreText.framework */,
|
||||
ED9FBC2D21830D2A005A5DF0 /* UIKit.framework */,
|
||||
307B49CE2059046B003D64E0 /* AdSupport.framework */,
|
||||
3077067920215DF600548664 /* libsqlite3.tbd */,
|
||||
3077067720215DF200548664 /* MediaPlayer.framework */,
|
||||
30E559E9200F1DE2001C0B78 /* libEgretNativeIOS.a */,
|
||||
306A7ABE200C89C000E1EBB6 /* OpenGLES.framework */,
|
||||
306A7ABC200C89B900E1EBB6 /* JavaScriptCore.framework */,
|
||||
306A7ABA200C898400E1EBB6 /* libicucore.tbd */,
|
||||
306A7AB8200C896F00E1EBB6 /* libc++.tbd */,
|
||||
306A7AB6200C892500E1EBB6 /* libiconv.tbd */,
|
||||
306A7AB4200C891B00E1EBB6 /* libz.tbd */,
|
||||
306A7AB2200C890E00E1EBB6 /* SystemConfiguration.framework */,
|
||||
306A7AB0200C890300E1EBB6 /* OpenAL.framework */,
|
||||
306A7AAE200C88F600E1EBB6 /* Foundation.framework */,
|
||||
306A7AAC200C88EA00E1EBB6 /* AudioToolbox.framework */,
|
||||
306A7AAA200C88E500E1EBB6 /* AVFoundation.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84860E502179DA92001FCEE7 /* doc */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84860E512179DA92001FCEE7 /* README_IOS.md */,
|
||||
);
|
||||
path = doc;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
306A7A8C200C83F500E1EBB6 /* 武极天下 */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 306A7AA4200C83F500E1EBB6 /* Build configuration list for PBXNativeTarget "武极天下" */;
|
||||
buildPhases = (
|
||||
306A7A89200C83F500E1EBB6 /* Sources */,
|
||||
306A7A8A200C83F500E1EBB6 /* Frameworks */,
|
||||
306A7A8B200C83F500E1EBB6 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "武极天下";
|
||||
packageProductDependencies = (
|
||||
D5FF445626A94B8500CF155C /* SwiftyJSON */,
|
||||
);
|
||||
productName = "武极天下";
|
||||
productReference = 306A7A8D200C83F500E1EBB6 /* 武极天下.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
306A7A85200C83F500E1EBB6 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1250;
|
||||
ORGANIZATIONNAME = egret;
|
||||
TargetAttributes = {
|
||||
306A7A8C200C83F500E1EBB6 = {
|
||||
CreatedOnToolsVersion = 8.3.3;
|
||||
DevelopmentTeam = 299H75LKGK;
|
||||
LastSwiftMigration = 1250;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 306A7A88200C83F500E1EBB6 /* Build configuration list for PBXProject "ios-template" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 306A7A84200C83F500E1EBB6;
|
||||
packageReferences = (
|
||||
D5FF445526A94B8500CF155C /* XCRemoteSwiftPackageReference "SwiftyJSON" */,
|
||||
);
|
||||
productRefGroup = 306A7A8E200C83F500E1EBB6 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
306A7A8C200C83F500E1EBB6 /* 武极天下 */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
306A7A8B200C83F500E1EBB6 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
305DF7A3200D95C5008022B6 /* game in Resources */,
|
||||
EDF3B7E524580A4B009DFBBD /* LaunchScreen.storyboard in Resources */,
|
||||
D5FF443326A80FA600CF155C /* m_loading.jpg in Resources */,
|
||||
306A7A9D200C83F500E1EBB6 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
306A7A89200C83F500E1EBB6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D5FF445026A80FFB00CF155C /* KeychainPasswordItem.swift in Sources */,
|
||||
D5FF443126A80F8600CF155C /* ViewController.swift in Sources */,
|
||||
D5FF442F26A80E5F00CF155C /* AppDelegate.swift in Sources */,
|
||||
D5FF444E26A80FF600CF155C /* IDUtil.swift in Sources */,
|
||||
306A7A98200C83F500E1EBB6 /* ViewController.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
306A7AA2200C83F500E1EBB6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = 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_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
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 = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
306A7AA3200C83F500E1EBB6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = 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_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
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 = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
306A7AA5200C83F500E1EBB6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "武极天下.entitlements";
|
||||
DEVELOPMENT_TEAM = 299H75LKGK;
|
||||
ENABLE_BITCODE = NO;
|
||||
HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/egret-libs/include";
|
||||
INFOPLIST_FILE = "ios-template/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/egret-libs";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jc.wjtx;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "ios-template/Wjtx-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
306A7AA6200C83F500E1EBB6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "武极天下.entitlements";
|
||||
DEVELOPMENT_TEAM = 299H75LKGK;
|
||||
ENABLE_BITCODE = NO;
|
||||
HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/egret-libs/include";
|
||||
INFOPLIST_FILE = "ios-template/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/egret-libs";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jc.wjtx;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "ios-template/Wjtx-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
306A7A88200C83F500E1EBB6 /* Build configuration list for PBXProject "ios-template" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
306A7AA2200C83F500E1EBB6 /* Debug */,
|
||||
306A7AA3200C83F500E1EBB6 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
306A7AA4200C83F500E1EBB6 /* Build configuration list for PBXNativeTarget "武极天下" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
306A7AA5200C83F500E1EBB6 /* Debug */,
|
||||
306A7AA6200C83F500E1EBB6 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
D5FF445526A94B8500CF155C /* XCRemoteSwiftPackageReference "SwiftyJSON" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/SwiftyJSON/SwiftyJSON";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 5.0.1;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
D5FF445626A94B8500CF155C /* SwiftyJSON */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D5FF445526A94B8500CF155C /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
|
||||
productName = SwiftyJSON;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 306A7A85200C83F500E1EBB6 /* Project object */;
|
||||
}
|
7
ios-template.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -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>
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "SwiftyJSON",
|
||||
"repositoryURL": "https://github.com/SwiftyJSON/SwiftyJSON",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "b3dcd7dbd0d488e1a7077cb33b00f2083e382f07",
|
||||
"version": "5.0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
BIN
ios-template.xcodeproj/project.xcworkspace/xcuserdata/zhl.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
@ -0,0 +1,35 @@
|
||||
<?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>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Playground (Playground) 1.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>Playground (Playground) 2.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
<key>orderHint</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
<key>Playground (Playground).xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>武极天下.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
5
ios-template/AppDelegate.h
Normal file
@ -0,0 +1,5 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@end
|
93
ios-template/AppDelegate.mm
Normal file
@ -0,0 +1,93 @@
|
||||
#import "AppDelegate.h"
|
||||
#import "ViewController.h"
|
||||
#import <EgretNativeIOS.h>
|
||||
|
||||
@implementation AppDelegate {
|
||||
EgretNativeIOS* _native;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
NSString* gameUrl = @"http://local/game/index.html";
|
||||
|
||||
_native = [[EgretNativeIOS alloc] init];
|
||||
_native.config.showFPS = true;
|
||||
_native.config.fpsLogTime = 30;
|
||||
_native.config.disableNativeRender = false;
|
||||
_native.config.clearCache = false;
|
||||
_native.config.useCutout = false;
|
||||
|
||||
UIViewController* viewController = [[ViewController alloc] initWithEAGLView:[_native createEAGLView]];
|
||||
if (![_native initWithViewController:viewController]) {
|
||||
return false;
|
||||
}
|
||||
[self setExternalInterfaces];
|
||||
|
||||
NSString* networkState = [_native getNetworkState];
|
||||
if ([networkState isEqualToString:@"NotReachable"]) {
|
||||
__block EgretNativeIOS* native = _native;
|
||||
[_native setNetworkStatusChangeCallback:^(NSString* state) {
|
||||
if (![state isEqualToString:@"NotReachable"]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[native startGame:gameUrl];
|
||||
});
|
||||
}
|
||||
}];
|
||||
return true;
|
||||
}
|
||||
|
||||
[_native startGame:gameUrl];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
|
||||
[_native pause];
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
|
||||
[_native resume];
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
// Saves changes in the application's managed object context before the application terminates.
|
||||
}
|
||||
|
||||
- (void)setExternalInterfaces {
|
||||
__block EgretNativeIOS* support = _native;
|
||||
[_native setExternalInterface:@"sendToNative" Callback:^(NSString* message) {
|
||||
NSString* str = [NSString stringWithFormat:@"Native get message: %@", message];
|
||||
NSLog(@"%@", str);
|
||||
[support callExternalInterface:@"sendToJS" Value:str];
|
||||
}];
|
||||
[_native setExternalInterface:@"@onState" Callback:^(NSString *message) {
|
||||
NSLog(@"Get @onState: %@", message);
|
||||
}];
|
||||
[_native setExternalInterface:@"@onError" Callback:^(NSString *message) {
|
||||
NSLog(@"Get @onError: %@", message);
|
||||
}];
|
||||
[_native setExternalInterface:@"@onJSError" Callback:^(NSString *message) {
|
||||
NSLog(@"Get @onJSError: %@", message);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_native destroy];
|
||||
}
|
||||
|
||||
@end
|
127
ios-template/AppDelegate.swift
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// 武极天下
|
||||
//
|
||||
// Created by zhl on 2021/7/21.
|
||||
// Copyright © 2021 egret. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Foundation
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
var _viewController: UIViewController?
|
||||
var _imageView: UIImageView?
|
||||
var _native: EgretNativeIOS = EgretNativeIOS.init()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
let gameUrl = "http://local/game/index.html"
|
||||
_native = EgretNativeIOS.init();
|
||||
_native.config.showFPS = false;
|
||||
_native.config.fpsLogTime = 30;
|
||||
_native.config.disableNativeRender = false;
|
||||
_native.config.clearCache = false;
|
||||
_native.config.useCutout = false;
|
||||
_native.config.enableGLBatch = true;
|
||||
|
||||
UIApplication.shared.isIdleTimerDisabled = true;
|
||||
|
||||
_viewController = ViewController.init(eaglView: _native.createEAGLView());
|
||||
if (!(_native.initWith(_viewController))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.setExternalInterfaces()
|
||||
let networkState:String? = _native.getNetworkState();
|
||||
if (networkState == "NotReachable") {
|
||||
print(">>>>>>>>>>>>>>>>>>>>no network")
|
||||
let native = _native;
|
||||
_native.startGame(gameUrl);
|
||||
self.showLoadingView();
|
||||
_native.setNetworkStatusChangeCallback({ (state) in
|
||||
if (state != "NotReachable") {
|
||||
DispatchQueue.main.async {
|
||||
native.startGame(gameUrl)
|
||||
self.showLoadingView();
|
||||
}
|
||||
}
|
||||
})
|
||||
return true;
|
||||
}
|
||||
_native.startGame(gameUrl);
|
||||
self.showLoadingView();
|
||||
return true
|
||||
}
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
func setExternalInterfaces() {
|
||||
let support = _native;
|
||||
_native.setExternalInterface("sendToNative", callback: { (message) -> () in
|
||||
var str: String = "";
|
||||
str.append(message!);
|
||||
support.callExternalInterface("sendToJS", value: str);
|
||||
})
|
||||
_native.setExternalInterface("@onState", callback: { (message) -> () in
|
||||
print("Get @onStage: %s", message as Any)
|
||||
})
|
||||
_native.setExternalInterface("@onError", callback: { (message) -> () in
|
||||
print("Get @onError: %s", message as Any)
|
||||
})
|
||||
_native.setExternalInterface("@onJSError", callback: { (message) -> () in
|
||||
print("Get @onJSError: %s", message as Any)
|
||||
})
|
||||
_native.setExternalInterface("@egretGameStarted", callback: { (message) -> () in
|
||||
print("Get @egretGameStarted: %s", message as Any)
|
||||
})
|
||||
_native.setExternalInterface("getUid", callback: { (message) -> () in
|
||||
print("Get @getUid: %s", message as Any)
|
||||
let id = IDUtil.getUid();
|
||||
let data = String(format:"{\"openid\":\"\", \"token\":\"%@\"}", arguments:[id]);
|
||||
support.callExternalInterface("sendUidToJS", value: data);
|
||||
})
|
||||
_native.setExternalInterface("removeNativeLoading", callback: { (message) -> () in
|
||||
print("Get @removeNativeLoading: %s", message as Any)
|
||||
self.hideLoadingView();
|
||||
})
|
||||
_native.setExternalInterface("hideLoadImg", callback: { (message) -> () in
|
||||
print("Get @hideLoadImg: %s", message as Any)
|
||||
self.hideLoadingView();
|
||||
})
|
||||
}
|
||||
func showLoadingView() {
|
||||
let image = UIImage(named: "m_loading.jpg");
|
||||
_imageView = UIImageView(image: image);
|
||||
_imageView?.contentMode = UIView.ContentMode.scaleAspectFill
|
||||
_imageView?.frame = _viewController!.view.frame;
|
||||
_viewController!.view.addSubview(_imageView!);
|
||||
_viewController!.view.bringSubviewToFront(_imageView!);
|
||||
}
|
||||
|
||||
func hideLoadingView(){
|
||||
_imageView?.removeFromSuperview();
|
||||
}
|
||||
|
||||
}
|
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/AppStoreIcon.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
116
ios-template/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
@ -0,0 +1,116 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "IconSmall-20@2x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-20@3x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall@2x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall@3x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-40@2x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-40@3x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon@2x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon@3x.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-20.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-20-iPad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-iPad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "IconSmall-40-iPad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-76@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-83.5@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "AppStoreIcon.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/Icon-76.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/Icon@2x.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/Icon@3x.png
Normal file
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 5.0 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/IconSmall-20.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 15 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/IconSmall-40.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 8.9 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/IconSmall.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/IconSmall@2x.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
ios-template/Assets.xcassets/AppIcon.appiconset/IconSmall@3x.png
Normal file
After Width: | Height: | Size: 18 KiB |
6
ios-template/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
47
ios-template/IDUtil.swift
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// IDUtil.swift
|
||||
// 武极天下
|
||||
//
|
||||
// Created by zhl on 2020/6/17.
|
||||
// Copyright © 2020 egret. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
public class IDUtil: NSObject{
|
||||
static let serviceName = "Wjtx"
|
||||
static let accessGroup: String? = nil
|
||||
static let accountName = "wjtx_uid"
|
||||
|
||||
public static func getUid() -> String {
|
||||
let id = getSavedUid()
|
||||
if (id != "") {
|
||||
return id
|
||||
}
|
||||
let strIDFV = UIDevice.current.identifierForVendor!.uuidString.lowercased();
|
||||
saveUid(uid: strIDFV)
|
||||
return strIDFV;
|
||||
}
|
||||
|
||||
static func saveUid(uid: String) {
|
||||
do {
|
||||
let passwordItem = KeychainPasswordItem(service: serviceName, account: accountName, accessGroup: accessGroup)
|
||||
try passwordItem.savePassword(uid)
|
||||
} catch {
|
||||
print("Error updating keychain - \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
static func getSavedUid() -> String {
|
||||
do {
|
||||
let passwordItem = KeychainPasswordItem(service: serviceName, account: accountName, accessGroup: accessGroup)
|
||||
let password = try passwordItem.readPassword()
|
||||
return password
|
||||
} catch {
|
||||
print("Error reading password from keychain - \(error)")
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
50
ios-template/Info.plist
Normal file
@ -0,0 +1,50 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
179
ios-template/KeychainPasswordItem.swift
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright (C) 2016 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
A struct for accessing generic password keychain items.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
struct KeychainPasswordItem {
|
||||
// MARK: Types
|
||||
|
||||
enum KeychainError: Error {
|
||||
case noPassword
|
||||
case unexpectedPasswordData
|
||||
case unexpectedItemData
|
||||
case unhandledError(status: OSStatus)
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
let service: String
|
||||
|
||||
private(set) var account: String
|
||||
|
||||
let accessGroup: String?
|
||||
|
||||
// MARK: Intialization
|
||||
|
||||
init(service: String, account: String, accessGroup: String? = nil) {
|
||||
self.service = service
|
||||
self.account = account
|
||||
self.accessGroup = accessGroup
|
||||
}
|
||||
|
||||
// MARK: Keychain access
|
||||
|
||||
func readPassword() throws -> String {
|
||||
/*
|
||||
Build a query to find the item that matches the service, account and
|
||||
access group.
|
||||
*/
|
||||
var query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
query[kSecMatchLimit as String] = kSecMatchLimitOne
|
||||
query[kSecReturnAttributes as String] = kCFBooleanTrue
|
||||
query[kSecReturnData as String] = kCFBooleanTrue
|
||||
|
||||
// Try to fetch the existing keychain item that matches the query.
|
||||
var queryResult: AnyObject?
|
||||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
// Check the return status and throw an error if appropriate.
|
||||
guard status != errSecItemNotFound else { throw KeychainError.noPassword }
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
// Parse the password string from the query result.
|
||||
guard let existingItem = queryResult as? [String : AnyObject],
|
||||
let passwordData = existingItem[kSecValueData as String] as? Data,
|
||||
let password = String(data: passwordData, encoding: String.Encoding.utf8)
|
||||
else {
|
||||
throw KeychainError.unexpectedPasswordData
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
|
||||
func savePassword(_ password: String) throws {
|
||||
// Encode the password into an Data object.
|
||||
let encodedPassword = password.data(using: String.Encoding.utf8)!
|
||||
|
||||
do {
|
||||
// Check for an existing item in the keychain.
|
||||
try _ = readPassword()
|
||||
|
||||
// Update the existing item with the new password.
|
||||
var attributesToUpdate = [String : AnyObject]()
|
||||
attributesToUpdate[kSecValueData as String] = encodedPassword as AnyObject?
|
||||
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
catch KeychainError.noPassword {
|
||||
/*
|
||||
No password was found in the keychain. Create a dictionary to save
|
||||
as a new keychain item.
|
||||
*/
|
||||
var newItem = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
newItem[kSecValueData as String] = encodedPassword as AnyObject?
|
||||
|
||||
// Add a the new item to the keychain.
|
||||
let status = SecItemAdd(newItem as CFDictionary, nil)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
}
|
||||
|
||||
mutating func renameAccount(_ newAccountName: String) throws {
|
||||
// Try to update an existing item with the new account name.
|
||||
var attributesToUpdate = [String : AnyObject]()
|
||||
attributesToUpdate[kSecAttrAccount as String] = newAccountName as AnyObject?
|
||||
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: self.account, accessGroup: accessGroup)
|
||||
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
self.account = newAccountName
|
||||
}
|
||||
|
||||
func deleteItem() throws {
|
||||
// Delete the existing item from the keychain.
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
let status = SecItemDelete(query as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
|
||||
static func passwordItems(forService service: String, accessGroup: String? = nil) throws -> [KeychainPasswordItem] {
|
||||
// Build a query for all items that match the service and access group.
|
||||
var query = KeychainPasswordItem.keychainQuery(withService: service, accessGroup: accessGroup)
|
||||
query[kSecMatchLimit as String] = kSecMatchLimitAll
|
||||
query[kSecReturnAttributes as String] = kCFBooleanTrue
|
||||
query[kSecReturnData as String] = kCFBooleanFalse
|
||||
|
||||
// Fetch matching items from the keychain.
|
||||
var queryResult: AnyObject?
|
||||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
// If no items were found, return an empty array.
|
||||
guard status != errSecItemNotFound else { return [] }
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
// Cast the query result to an array of dictionaries.
|
||||
guard let resultData = queryResult as? [[String : AnyObject]] else { throw KeychainError.unexpectedItemData }
|
||||
|
||||
// Create a `KeychainPasswordItem` for each dictionary in the query result.
|
||||
var passwordItems = [KeychainPasswordItem]()
|
||||
for result in resultData {
|
||||
guard let account = result[kSecAttrAccount as String] as? String else { throw KeychainError.unexpectedItemData }
|
||||
|
||||
let passwordItem = KeychainPasswordItem(service: service, account: account, accessGroup: accessGroup)
|
||||
passwordItems.append(passwordItem)
|
||||
}
|
||||
|
||||
return passwordItems
|
||||
}
|
||||
|
||||
// MARK: Convenience
|
||||
|
||||
private static func keychainQuery(withService service: String, account: String? = nil, accessGroup: String? = nil) -> [String : AnyObject] {
|
||||
var query = [String : AnyObject]()
|
||||
query[kSecClass as String] = kSecClassGenericPassword
|
||||
query[kSecAttrService as String] = service as AnyObject?
|
||||
|
||||
if let account = account {
|
||||
query[kSecAttrAccount as String] = account as AnyObject?
|
||||
}
|
||||
|
||||
if let accessGroup = accessGroup {
|
||||
query[kSecAttrAccessGroup as String] = accessGroup as AnyObject?
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
}
|
||||
|
43
ios-template/LaunchScreen.storyboard
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||
<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">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="qhh-TY-2DC"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Oj5-df-MCz"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="m_loading.jpg" translatesAutoresizingMaskIntoConstraints="NO" id="LXY-iL-70L">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="LXY-iL-70L" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="MZ2-ry-so8"/>
|
||||
<constraint firstAttribute="trailing" secondItem="LXY-iL-70L" secondAttribute="trailing" id="XU5-3v-LZR"/>
|
||||
<constraint firstItem="LXY-iL-70L" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="lhr-mm-KUV"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LXY-iL-70L" secondAttribute="bottom" id="yXs-ym-TTY"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="52.173913043478265" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="m_loading.jpg" width="640" height="1280"/>
|
||||
</resources>
|
||||
</document>
|
7
ios-template/ViewController.h
Normal file
@ -0,0 +1,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ViewController : UIViewController
|
||||
|
||||
- (instancetype)initWithEAGLView:(UIView*)eaglView;
|
||||
|
||||
@end
|
24
ios-template/ViewController.mm
Normal file
@ -0,0 +1,24 @@
|
||||
#import "ViewController.h"
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
- (instancetype)initWithEAGLView:(UIView*)eaglView {
|
||||
if (self = [super init]) {
|
||||
self.view = eaglView;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
||||
return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
|
||||
@end
|
27
ios-template/ViewController.swift
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// 武极天下
|
||||
//
|
||||
// Created by zhl on 2021/7/21.
|
||||
// Copyright © 2021 egret. All rights reserved.
|
||||
//
|
||||
import UIKit
|
||||
import Foundation
|
||||
class ViewController: UIViewController {
|
||||
convenience init(eaglView: UIView) {
|
||||
self.init();
|
||||
self.view = eaglView;
|
||||
}
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
return true;
|
||||
}
|
||||
//
|
||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
return .portrait
|
||||
}
|
||||
//
|
||||
override var shouldAutorotate: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
111
ios-template/ios-template/AppDelegate.swift
Normal file
@ -0,0 +1,111 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// 武极天下
|
||||
//
|
||||
// Created by zhl on 2020/6/17.
|
||||
// Copyright © 2020 egret. All rights reserved.
|
||||
//
|
||||
import UIKit
|
||||
import Foundation
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
var _viewController: UIViewController?
|
||||
var _imageView: UIImageView?
|
||||
var _native: EgretNativeIOS = EgretNativeIOS.init()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
let gameUrl = "http://local/game/index.html"
|
||||
_native = EgretNativeIOS.init();
|
||||
_native.config.showFPS = false;
|
||||
_native.config.fpsLogTime = 30;
|
||||
_native.config.disableNativeRender = false;
|
||||
_native.config.clearCache = false;
|
||||
_native.config.useCutout = true;
|
||||
|
||||
UIApplication.shared.isIdleTimerDisabled = true;
|
||||
|
||||
_viewController = ViewController.init(eaglView: _native.createEAGLView());
|
||||
if (!(_native.initWith(_viewController))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.setExternalInterfaces()
|
||||
let networkState:String? = _native.getNetworkState();
|
||||
if (networkState == "NotReachable") {
|
||||
let native = _native;
|
||||
_native.setNetworkStatusChangeCallback({ (state) in
|
||||
if (state != "NotReachable") {
|
||||
DispatchQueue.main.async {
|
||||
native.startGame(gameUrl)
|
||||
self.showLoadingView();
|
||||
}
|
||||
}
|
||||
})
|
||||
return true;
|
||||
}
|
||||
_native.startGame(gameUrl);
|
||||
self.showLoadingView();
|
||||
return true
|
||||
}
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
func setExternalInterfaces() {
|
||||
let support = _native;
|
||||
_native.setExternalInterface("sendToNative", callback: { (message) -> () in
|
||||
var str: String = "";
|
||||
str.append(message!);
|
||||
support.callExternalInterface("sendToJS", value: str);
|
||||
})
|
||||
_native.setExternalInterface("@onState", callback: { (message) -> () in
|
||||
print("Get @onStage: %s", message as Any)
|
||||
})
|
||||
_native.setExternalInterface("@onError", callback: { (message) -> () in
|
||||
print("Get @onError: %s", message as Any)
|
||||
})
|
||||
_native.setExternalInterface("getUid", callback: { (message) -> () in
|
||||
print("Get @getUid: %s", message as Any)
|
||||
let id = IDUtil.getUid();
|
||||
support.callExternalInterface("sendUidToJS", value: id);
|
||||
})
|
||||
_native.setExternalInterface("removeNativeLoading", callback: { (message) -> () in
|
||||
print("Get @removeNativeLoading: %s", message as Any)
|
||||
self.hideLoadingView();
|
||||
})
|
||||
}
|
||||
func showLoadingView() {
|
||||
let image = UIImage(named: "m_loading.jpg");
|
||||
_imageView = UIImageView(image: image);
|
||||
_imageView?.contentMode = UIView.ContentMode.scaleAspectFill
|
||||
_imageView?.frame = _viewController!.view.frame;
|
||||
_viewController!.view.addSubview(_imageView!);
|
||||
_viewController!.view.bringSubviewToFront(_imageView!);
|
||||
}
|
||||
|
||||
func hideLoadingView(){
|
||||
_imageView?.removeFromSuperview();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
6
ios-template/ios-template/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
47
ios-template/ios-template/IDUtil.swift
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// IDUtil.swift
|
||||
// 武极天下
|
||||
//
|
||||
// Created by zhl on 2020/6/17.
|
||||
// Copyright © 2020 egret. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
public class IDUtil: NSObject{
|
||||
static let serviceName = "Wjtx"
|
||||
static let accessGroup: String? = nil
|
||||
static let accountName = "wjtx_uid"
|
||||
|
||||
public static func getUid() -> String {
|
||||
let id = getSavedUid()
|
||||
if (id != "") {
|
||||
return id
|
||||
}
|
||||
let strIDFV = UIDevice.current.identifierForVendor!.uuidString.lowercased();
|
||||
saveUid(uid: strIDFV)
|
||||
return strIDFV;
|
||||
}
|
||||
|
||||
static func saveUid(uid: String) {
|
||||
do {
|
||||
let passwordItem = KeychainPasswordItem(service: serviceName, account: accountName, accessGroup: accessGroup)
|
||||
try passwordItem.savePassword(uid)
|
||||
} catch {
|
||||
print("Error updating keychain - \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
static func getSavedUid() -> String {
|
||||
do {
|
||||
let passwordItem = KeychainPasswordItem(service: serviceName, account: accountName, accessGroup: accessGroup)
|
||||
let password = try passwordItem.readPassword()
|
||||
return password
|
||||
} catch {
|
||||
print("Error reading password from keychain - \(error)")
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
52
ios-template/ios-template/Info.plist
Normal file
@ -0,0 +1,52 @@
|
||||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
179
ios-template/ios-template/KeychainPasswordItem.swift
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright (C) 2016 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
A struct for accessing generic password keychain items.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
struct KeychainPasswordItem {
|
||||
// MARK: Types
|
||||
|
||||
enum KeychainError: Error {
|
||||
case noPassword
|
||||
case unexpectedPasswordData
|
||||
case unexpectedItemData
|
||||
case unhandledError(status: OSStatus)
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
let service: String
|
||||
|
||||
private(set) var account: String
|
||||
|
||||
let accessGroup: String?
|
||||
|
||||
// MARK: Intialization
|
||||
|
||||
init(service: String, account: String, accessGroup: String? = nil) {
|
||||
self.service = service
|
||||
self.account = account
|
||||
self.accessGroup = accessGroup
|
||||
}
|
||||
|
||||
// MARK: Keychain access
|
||||
|
||||
func readPassword() throws -> String {
|
||||
/*
|
||||
Build a query to find the item that matches the service, account and
|
||||
access group.
|
||||
*/
|
||||
var query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
query[kSecMatchLimit as String] = kSecMatchLimitOne
|
||||
query[kSecReturnAttributes as String] = kCFBooleanTrue
|
||||
query[kSecReturnData as String] = kCFBooleanTrue
|
||||
|
||||
// Try to fetch the existing keychain item that matches the query.
|
||||
var queryResult: AnyObject?
|
||||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
// Check the return status and throw an error if appropriate.
|
||||
guard status != errSecItemNotFound else { throw KeychainError.noPassword }
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
// Parse the password string from the query result.
|
||||
guard let existingItem = queryResult as? [String : AnyObject],
|
||||
let passwordData = existingItem[kSecValueData as String] as? Data,
|
||||
let password = String(data: passwordData, encoding: String.Encoding.utf8)
|
||||
else {
|
||||
throw KeychainError.unexpectedPasswordData
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
|
||||
func savePassword(_ password: String) throws {
|
||||
// Encode the password into an Data object.
|
||||
let encodedPassword = password.data(using: String.Encoding.utf8)!
|
||||
|
||||
do {
|
||||
// Check for an existing item in the keychain.
|
||||
try _ = readPassword()
|
||||
|
||||
// Update the existing item with the new password.
|
||||
var attributesToUpdate = [String : AnyObject]()
|
||||
attributesToUpdate[kSecValueData as String] = encodedPassword as AnyObject?
|
||||
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
catch KeychainError.noPassword {
|
||||
/*
|
||||
No password was found in the keychain. Create a dictionary to save
|
||||
as a new keychain item.
|
||||
*/
|
||||
var newItem = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
newItem[kSecValueData as String] = encodedPassword as AnyObject?
|
||||
|
||||
// Add a the new item to the keychain.
|
||||
let status = SecItemAdd(newItem as CFDictionary, nil)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
}
|
||||
|
||||
mutating func renameAccount(_ newAccountName: String) throws {
|
||||
// Try to update an existing item with the new account name.
|
||||
var attributesToUpdate = [String : AnyObject]()
|
||||
attributesToUpdate[kSecAttrAccount as String] = newAccountName as AnyObject?
|
||||
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: self.account, accessGroup: accessGroup)
|
||||
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
self.account = newAccountName
|
||||
}
|
||||
|
||||
func deleteItem() throws {
|
||||
// Delete the existing item from the keychain.
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
let status = SecItemDelete(query as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
|
||||
static func passwordItems(forService service: String, accessGroup: String? = nil) throws -> [KeychainPasswordItem] {
|
||||
// Build a query for all items that match the service and access group.
|
||||
var query = KeychainPasswordItem.keychainQuery(withService: service, accessGroup: accessGroup)
|
||||
query[kSecMatchLimit as String] = kSecMatchLimitAll
|
||||
query[kSecReturnAttributes as String] = kCFBooleanTrue
|
||||
query[kSecReturnData as String] = kCFBooleanFalse
|
||||
|
||||
// Fetch matching items from the keychain.
|
||||
var queryResult: AnyObject?
|
||||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
// If no items were found, return an empty array.
|
||||
guard status != errSecItemNotFound else { return [] }
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
// Cast the query result to an array of dictionaries.
|
||||
guard let resultData = queryResult as? [[String : AnyObject]] else { throw KeychainError.unexpectedItemData }
|
||||
|
||||
// Create a `KeychainPasswordItem` for each dictionary in the query result.
|
||||
var passwordItems = [KeychainPasswordItem]()
|
||||
for result in resultData {
|
||||
guard let account = result[kSecAttrAccount as String] as? String else { throw KeychainError.unexpectedItemData }
|
||||
|
||||
let passwordItem = KeychainPasswordItem(service: service, account: account, accessGroup: accessGroup)
|
||||
passwordItems.append(passwordItem)
|
||||
}
|
||||
|
||||
return passwordItems
|
||||
}
|
||||
|
||||
// MARK: Convenience
|
||||
|
||||
private static func keychainQuery(withService service: String, account: String? = nil, accessGroup: String? = nil) -> [String : AnyObject] {
|
||||
var query = [String : AnyObject]()
|
||||
query[kSecClass as String] = kSecClassGenericPassword
|
||||
query[kSecAttrService as String] = service as AnyObject?
|
||||
|
||||
if let account = account {
|
||||
query[kSecAttrAccount as String] = account as AnyObject?
|
||||
}
|
||||
|
||||
if let accessGroup = accessGroup {
|
||||
query[kSecAttrAccessGroup as String] = accessGroup as AnyObject?
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
}
|
||||
|
29
ios-template/ios-template/LaunchScreen.storyboard
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
||||
<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">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="qhh-TY-2DC"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Oj5-df-MCz"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="52.173913043478265" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
7
ios-template/ios-template/ViewController.h
Normal file
@ -0,0 +1,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ViewController : UIViewController
|
||||
|
||||
- (instancetype)initWithEAGLView:(UIView*)eaglView;
|
||||
|
||||
@end
|
24
ios-template/ios-template/ViewController.mm
Normal file
@ -0,0 +1,24 @@
|
||||
#import "ViewController.h"
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
- (instancetype)initWithEAGLView:(UIView*)eaglView {
|
||||
if (self = [super init]) {
|
||||
self.view = eaglView;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
||||
return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
|
||||
@end
|
28
ios-template/ios-template/ViewController.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// 武极天下
|
||||
//
|
||||
// Created by zhl on 2020/6/17.
|
||||
// Copyright © 2020 egret. All rights reserved.
|
||||
//
|
||||
import UIKit
|
||||
import Foundation
|
||||
class ViewController: UIViewController {
|
||||
convenience init(eaglView: UIView) {
|
||||
self.init();
|
||||
self.view = eaglView;
|
||||
}
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
return true;
|
||||
}
|
||||
//
|
||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
return .portrait
|
||||
}
|
||||
//
|
||||
override var shouldAutorotate: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
6
ios-template/ios-template/Wjtx-Bridging-Header.h
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import <EgretNativeIOS.h>
|
||||
|
BIN
ios-template/ios-template/icon.png
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
ios-template/ios-template/m_loading.jpg
Executable file
After Width: | Height: | Size: 59 KiB |
BIN
ios-template/m_loading.jpg
Executable file
After Width: | Height: | Size: 59 KiB |
13
ios-template/main.m
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// main.m
|
||||
// Copyright © 2018-2020 egret. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
7
ios-template/wjtx-Bridging-Header.h
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import <EgretNativeIOS.h>
|
||||
|
||||
|
10
ios-template/武极天下.entitlements
Normal file
@ -0,0 +1,10 @@
|
||||
<?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>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.ztgame.wjtxh5</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
10
武极天下.entitlements
Normal file
@ -0,0 +1,10 @@
|
||||
<?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>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.jc.wjtx</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|