最近开发的项目需求:访问手机本地相册,且实现多选图片。
网上搜索了一下,实现多选功能手动开发的话较为繁琐,本人对于IOS开发也只是略懂一二,所以决定借助TZImagePickerC框架来实现功能,中文框架,使用起来相对较为方便。框架Git地址:https://github.com/banchichen/TZImagePickerController
Unity和IOS交互
Unity打包IOS端后会生成xcode工程项目,需要借助xcode二次打包进行真机测试或发布。Unity与IOS的交互其实是C#和objectC间的交互。需要在Unity Asset资源的Plugins特殊文件夹下创建oc的头文件和实现文件。然后在C#脚本中调用OC方法
创建一个脚本用来交互,
using System.Runtime.InteropServices;
//oc方法--unity调ios
[DllImport ("__Internal")]
private static extern void _iosSelectPhotos();
//回掉方法--ios调oc
public void PickImageCallBack_Base64(string json_base64)
{
Debug.Log($"返回Json为{json_base64}");
//参数问json格式字符串,转换后为选择的base64格式的图片
}
[DllImport ("__Internal")]的作用是说明此函数是dll导入的函数,需要也就是从Plugins中创建的oc实体文件中的特殊方法。声明的方法需要用private static extern声明。是多选照片的入口方法,访问Btn调此方法。
PickImageCallBack_Base64方法则是oc实体文件中获取完照片后回调给Unity的方法,具体用法写在oc实体文件内。
脚本写完后在Plugins文件夹下创建如下结构文件:
文件后缀一个为.h另一个是.mm
文件内容可以现在编辑,也可以打包出来后用xcode编辑,当然也可以打包出来后用xcode创建,这里选择的是用xcode编辑。
创建完成后进行打包。
打开Unity-iPhone.xcodeproj(需要安装xcode)
首先将TZImagePickerController导入工程中,Git上下载的TZImagePickerController文件无法直接导入Unity工程,印象中是需要修改所有typeof的地方,不懂ios开发的朋友可以先导入试一下,报错后改一改。不想改的在可以在这里自取。
导入方法直接将TZImagePickerController文件夹拖入左侧预览框项目文件外层。
Finish后即可对IOSAlbumController进行编辑。
在xcode中找到刚才在plugins内创建的文件,路径应该是Libraries—Plugins—IOS下。
先对.h头文件进行编写:
@interface IOSAlbumController:UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@end
再编写.mm文件
#import "TZImagePickerController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/Photos.h>
#import "TZImageManager.h"
#import "IOSAlbumController.h"
@interface IOSAlbumController()<TZImagePickerControllerDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate,UICollectionViewDelegate,UICollectionViewDataSource>{
NSMutableArray * _selectedAssets;
NSMutableArray * _selectedPhotos;
}
@end
@implementation IOSAlbumController
//访问相册选择图片的的主方法
-(void)pushTZImagePickerController{
TZImagePickerController *imagePC=[[TZImagePickerController alloc]initWithMaxImagesCount:30 delegate:self];
imagePC.allowPickingVideo=NO;
imagePC.allowPickingOriginalPhoto=NO;
imagePC.selectedAssets=_selectedAssets;
//以上内容照抄即可,大概就是打开相册选择照片
//参数photos为选择图片完成后的回调,为UIImage类型的数组。
[imagePC setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
//将photos数组转换为base64数组
NSMutableArray *muArray=[NSMutableArray arrayWithCapacity:2];
for (UIImage *object in photos) {
NSString *image64= [self imageToString:object];
[muArray addObject:image64];
}
//因为没有找到UnitySendMessage的重载,第三个参数只能传入 nsstring类型转换成的char数组(貌似是,自己理解的)
//所以将base64数组转换为json传回unity
NSDictionary *param=[NSDictionary dictionaryWithObjectsAndKeys:muArray,@"Json", nil];
NSError *error=nil;
NSData *jsonData=[NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:&error];
NSString *str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
//转换json
UnitySendMessage("Interact", "PickImageCallBack_Base64", str.UTF8String);
//以下照抄
[_selectedPhotos removeAllObjects];
[_selectedAssets removeAllObjects];
_selectedAssets=[NSMutableArray arrayWithArray:assets];
_selectedPhotos=[NSMutableArray arrayWithArray:photos];
}];
[self presentViewController:imagePC animated:YES completion:nil];
}
//image转base64的工具方法
- (NSString *)imageToString:(UIImage *)image {
NSData *imagedata = UIImagePNGRepresentation(image);
NSString *image64 = [imagedata base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return image64;
}
@end
//unity与ios交互s是通过C语言进行交互,在oc中声明如下C语言代码块
#if defined(__cplusplus)
extern "C"{
#endif
//与在Unity创建脚本时声明的方法名一致
void _iosOpenPhotoLibrary(){
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
IOSAlbumController *app=[[IOSAlbumController alloc]init];
UIViewController *vc=UnityGetGLViewController();
[vc.view addSubview: app.view ];
//前面是打开一个view
//调用上面的pushTZImagePickerController方法
[app pushTZImagePickerController];
}
else
{
//回调回unity的方法,三个参数,
//第一个,回调脚本(也就是刚才在unity里创建的脚本)所挂载在unity中的GameObject的名字,推荐与脚本同名。
//第二个,脚本内方法名
//第三个,char类型数组(好像是,应该差不多)
UnitySendMessage("Interact", "PickImageCallBack_Base64", (@"").UTF8String);
}
}
#if defined(__cplusplus)
}
#endif
到此就完成了所有的代码部分,更恶心的地方在xcode的配置,想要真机测试需要apple id和证书下载,真机测试都是免费的,网上有很多帖子,自寻。
写一下我遇到的问题,建议先按照我的问题配置完毕后再打包找错:
1.在TARGETS–General–Frameworks,Libraries,and EmbeddedContent下
添加
CoreLoaction.frameworks;
CoreServices.frameworks;
Photos.frameworks;
ImageIO.frameworks
2.在TARGETS–Info–Custom IOS Target Properties下,添加Privacy - Photo Library Usage Description键(调用相册时需要询问访问权限,如果需要相机的话也需要加Camera的键,下拉菜单里选择就可以)
3.如果报annot use ‘@try’ with Objective-C exceptions disabled 的错误(最好先打开)
去Targets–BulidSettings – all – combined
Apple Clang-Language-Objective-c
enable objective-c exceptions --yes
然后就可以进行真机测试,如果还有其他问题可以百度或留言。