目录
1、代码中更改Icon图标
1. 代码中更改Icon图标(更换图标,会弹出确认框,仅支持13及以上系统)
第1步. 修改Info.plist
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>原AppIcon图标名</string>
</array>
</dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>icon01</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon图标名2</string>
</array>
</dict>
<key>icon02</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon图标名3</string>
</array>
</dict>
</dict>
</dict>
第2步. 将所有AppIcon放入工程中(不要放在Assets.xcassets)
第3步. 代码
// 更换
if ([UIApplication sharedApplication].supportsAlternateIcons) {
[[UIApplication sharedApplication] setAlternateIconName:图标名key字符串 completionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"success:%@",图标名);
}else{
NSLog(@"error:%@",error);
}
}];
} else {
NSLog(@"不能更换icon");
return;
}
}
// 还原
if ([UIApplication sharedApplication].alternateIconName != nil) { // 图标被替换过
// 重置icon
[[UIApplication sharedApplication] setAlternateIconName:nil completionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"success");
} else {
NSLog(@"error:%@",error);
}
}];
}
示例
dispatch_async(dispatch_get_main_queue(), ^{
// 更换图标,会弹出确认框
if (@available(iOS 10.3, *)) {
if ([UIApplication sharedApplication].supportsAlternateIcons) {
[[UIApplication sharedApplication] setAlternateIconName:@"icon01" completionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"success:%@",@"icon02");
}else{
NSLog(@"error:%@",error);
}
}];
} else {
NSLog(@"不能更换icon");
return;
}
} else {
// Fallback on earlier versions
}
});
2. 制作静态库
库是代码集合,是共享代码的一种方式。2种方式:
开源:公开源代码
闭源:静态库(.a .framework) / 动态库(.dylib .framework)
静态库:在链接阶段,会将文件完全复制过来。冗余占内存
动态库:程序运行时有系统加载到内存供程序调用,仅加载一次。
注意
自定义的动态库不允许上传AppStore
.a文件(纯二进制)不能单独使用,需要.h配合。
.framework文件(包含二进制,.h,plist等)可单独使用。
制作.a
1.新建项目(选择CocoaTouch StaticLibrary),并写入相关代码
2.项目|buildPhases|+|New Header Phase|拖入对外头文件
3.选择真机编译(拿到.a),选择模拟器编译(拿到.a) (2者是不一样的,Debug-iphoneos文件夹中是真机,Debug-iphonesimulator文件夹中是模拟器)
4.终端合并2.a (lipo -create Debug-iphoneos/xxx.a Debug-iphonesimulator/xxx.a -output xxx.a) 可改变路径 /Users/cx/Desktop/...
5.使用.a, 将.a和include中的文件拖入项目中
制作.framework
1.新建项目(选择CocoaTouch Framework),并写入相关代码
2.项目|buildPhases|+|New Header Phase|拖入对外头文件
项目|编辑区左上角Add Target|Cross-platform|Aggregate| Build Phases | + | NewRunScript Phase
# Sets the target folders and the final framework product.
# 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target"${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target"${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/""${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}""${SIMULATOR_DIR}/${FMK_NAME}" -output"${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${SRCROOT}/Products/"
项目|项目target|Build Settings|Mach-O Type 选择StaticLibrary
选择AggregateTarget进行编译(自动弹出Product文件夹)
使用
导入.framework
#import<>
查看支持的arm架构
lipo -info framework
制作.bundle
bundle文件:静态文件,不参加编译,作为资源解析成特殊的二进制数据
新建bundle
新建项目(选择macOS|bundle)| 放入图片 | 编译 | 拿到.bundle
使用
[UIImageimageNamed:@"TestBundle.bundle/Contents/Resources/1.png"]
记录崩溃日志
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 设置处理崩溃方法(闪退时调用)
NSSetUncaughtExceptionHandler(&ExceptionHandler);
}
void ExceptionHandler(NSException *exception){
//
NSArray *arr=[exception callStackSymbols];
// 闪退原因
NSString *reason=[exception reason];
// 闪退名
NSString *name=[exception name];
// 当前版本号
NSString *currentVersion=[[[NSBundle mainBundle]infoDictionary]objectForKey:@"CFBundleversion"];
// 调接口
}
唯一标识
在iOS5前可以获取唯一标识UDID(Unique Device Identifier)。
思路(在非越狱的手机上):
1.获取某个硬件信息生成唯一标识。第一找苹果的漏洞,第二调用私有接口。不可持续发展
2.获取操作系统信息生成唯一标识。在系统升级、卸载重装、备份恢复都可以保留,但重置手机系统会清除。
国内
友盟用的是 Openudid + IDFA
TalkingData用的是 Keychain + IDFA
Openudid
github上开源项目
原理:利用iOS系统中的UIPasteboard剪贴板类通过键值对来存储一个160位的随机字符串。
iOS7之后,苹果封堵了剪贴板通信的漏洞,之前所有的应用都可以共享同一个剪贴板存储内容。现在只有在同一CFBundleIdentifier标识下的App才能共享内容,如com.koudai.a和com.koudai.b。
keychain
keychain钥匙串,是一个苹果用来存储密码和证书的加密存储区域,目的是为了帮助用户安全存储应用或者浏览器的密码,减少了很多输入密码和记密码的麻烦。
keychain存储在手机的某个公共区域(不是沙盒),因此卸载应用并不影响但重置系统会清除,可以拿keychain来存储唯一标识。
UUID, 全球独立标识(Globally Unique Identifier)
重复概率为170亿分之一
NSString *uuid = [[NSUUID UUID] UUIDString];
IDFA
ASIdentifierManager单例(AdSupport.framework框架)提供了一个方法advertisingIdentifier,返回一个的NSUUID实例
重置系统或还原广告标示符(设置程序|通用|关于本机|广告|还原广告标示符)是会清除
使用IDFA(必须勾选IDFA选项)但未集成任何广告服务的应用审核都会被拒