CESDK IOS环境搭建

IOS环境搭建相对于Android来说要简单一些,不过对于我来说难点在于Xcode不熟,并且OC也不会-.-

自动打包

PostProcessBuild

在开始构建项目之前,先要解决的是自动打包. Unity在新版中已经提供了PBXProject,用起来很方便.

在任意的Editor目录下加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class XCodeProcessAgent
{
private PBXProject mProject;
private string mTargetGuid;
private string mProjPath;

public void Initialize(string _pathToBuiltProject)
{
mProjPath = _pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";
mProject = new PBXProject();
mProject.ReadFromFile(mProjPath);
mTargetGuid = mProject.TargetGuidByName("Unity-iPhone");
}

public void Save()
{
mProject.WriteToFile(mProjPath);
}

public void AddFramework(string _framework)
{
mProject.AddFrameworkToProject(mTargetGuid, _framework, true);
Debug.Log("[CESDK Unity] add framework : " + _framework);
}

public void SetBuildProperty(string _property, string _value)
{
mProject.SetBuildProperty(mTargetGuid, _property, _value);
Debug.Log("[CESDK Unity] set property : " + _property + " value to: " + _value);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public static class CESDKPostProcessBuild
{
//[PostProcessBuild]
[PostProcessBuild(88)]
public static void onPostProcessBuild(BuildTarget target, string pathToBuiltProject)
{
if (target != BuildTarget.iOS)
{
Debug.LogWarning("Target is not iPhone. XCodePostProcess will not run");
return;
}

Debug.Log("[CESDK Unity]: Run IOS XCode Process");

EditProject(pathToBuiltProject);

Debug.Log("[CESDK Unity]: Finish");
}


private static void EditProject(string _pathToBuiltProject)
{
var agent = new XCodeProcessAgent();
agent.Initialize(_pathToBuiltProject);

//============
//==添加Framework
//============
agent.AddFramework("AVKit.framework");

//===============
//==设置Property
//===============
agent.SetBuildProperty("ENABLE_BITCODE", "false");


//最后调用保存
agent.Save();
}
}

PostProcessBuild标签内部的是执行顺序. 当点击Build时候就会按指定顺序开始执行一个个函数.

目前我接入一个打点SDK,需要自己import一些Framework,然后每次需要更改BitCode=false,至于其他的可以自行添加
Mob的ShareSDK内部也有一个PBXProject,应该是他们为了兼容旧版本Unity或者其他原因自己搞了一个. 他们内部也修改了白名单等(用于回调微信等app)

Automatically Sign

自动设置TeamID

QQ20171208-181634

这个要先在官网上查到对应的TeamID

BaiduNetdisk_mac_2.2.2

然后直接填入PlayerSetting中即可

AppStore 1024x1024 Icon

直接导出项目会报Warning

Missing Marketing Icon - iOS Apps must include a 1024x1024px Marketing Icon in PNG format. Apps that do not include the Marketing Icon cannot be submitted for App Review or Beta App Review.

然后上传AppStore时候也不会让过.

QQ20171209-163315

需要手动勾选 Override for iOS,然后全部填上对应的Icon即可

相互通讯

OK,写了PostProcessBuild脚本后,就可以直接导出一个可运行的Xcode项目了. 下一步是尝试写一个可以互相通讯的静态Library

创建Library项目

Xcode直接创建一个静态的Library, 我的叫LibCA

QQ20171209-163500

XCode部分

更改LibCA.mm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#import "LibCA.h"

#if defined (__cplusplus)
extern "C" {
#endif

extern void UnitySendMessage(const char *, const char *, const char *);

const char* UnityStringFromNSString(NSString* string)
{
const char* cString = string.UTF8String;
char* _unityString = (char*)malloc(strlen(cString) + 1);
strcpy(_unityString, cString);
return _unityString;
}

NSString* NSStringFromUnityString(const char* unityString_)
{
if (unityString_ == nil) return [NSString new];
return [NSString stringWithUTF8String:unityString_];
}

int GetVersion() {
return 1;
}

const char* GetMessage(){
return UnityStringFromNSString(@"CESDK in running");
}

void NotifyUnity()
{
UnitySendMessage("CESDK", "NotifyFromXcode","{\"age\":15}");
}


#if defined (__cplusplus)
}
#endif

@implementation LibCA
@end

其中

1
extern void UnitySendMessage(const char *, const char *, const char *);

UnitySendMessage标明extern表示该函数已经在本文件以外(Unity内部函数)定义好了,这里声明一下可以直接使用.

使用的时候

1
UnitySendMessage("CESDK", "NotifyFromXcode","{\"age\":15}");
  • 第一个参数:CESDK 是对应的GameObject的Name
  • 第二个参数:NotifyFromXcode 内部函数名
  • 第三个参数:传参,直接用JSON,然后C#内用MinJSON解开即可

Unity部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TestButton : MonoBehaviour
{
[DllImport("__Internal")]
private static extern string GetMessage();

[DllImport("__Internal")]
private static extern void NotifyUnity();

public void CallToGetMessage()
{
CELog.Log("On CallToGetMessage");
CELog.Log("Message is : " + GetMessage());
}

public void CallToNotifyUnity()
{
CELog.Log("On CallToNotifyUnity");
NotifyUnity();
}

public void NotifyFromXcode(string _arg)
{
CELog.Log("Receive msg: " + _arg);
}
}

QQ20171209-164337

写一个MonoBehaviour挂载到根目录叫CESDK的GameObject上面,使用[DllImport("__Internal")]表示下面的函数由Xcode内提供,Unity直接调用即可.

自动构建Library

QQ20171209-164841

修改生成的Library,按上图的设置方式,可以直接Copy到Unity的Assets/Plugins目录下.

这样每次改变,只需要在Xcode中执行Command+B即可

遇到的错误

Invalid bitcode signature

导出的Lib运行会报告Bitcode签名有问题,因为我主项目已经禁用了Bitcode
47281059

所以需要在Library项目中也禁用Bitcode
47253864

Apple Mach-O Linker Undefined symbols for architecture armv7

这个困扰我好久,发现如果我在项目中直接写代码,函数就可以找到,如果我以Lib方式引入进来就找不到

47397332

原因是因为Unity导出的项目 iOS Deployment Target 默认是7.0, 但是Xcode创建新项目,默认则是最新的11.1.

QQ20171209-165552

直接把Lib项目的Target改成最低8.0即可.

此时项目可以Run,只是会报Warning说Lib是8.0,但是Unity中指定的是7.0不过还是可以运行.

运行效果

QQ20171209-154638

其他

ShareSDK中有一个叫ShareSDKUnity3DBridge的文件. 我理解的他应该是通过PBXProject在Build项目时候,直接将该文件Copy到Class目录下.从而不用写静态库. 虽然不理解这样做的好处. 不过也是个思路. 包括对应Android项目分平台用不同的jar包.也可以先把所有的jar包放工程外,然后通过PBXProject分平台引用不同的Jar从而减小体积.

坚持原创技术分享,您的支持将鼓励我继续创作!