iOS开发基础57-换肤功能与静态库开发指南
一、iOS 换肤功能
1. 换肤功能的思路
实现换肤功能的几点思路:
-
解决方案1:基于颜色的图片命名规范
- 问题1:每套图片的文件名必须遵循“颜色+名称.png”格式。
- 问题2:如果将某一图片应用到其他皮肤时会比较麻烦。
-
解决方案2:利用 Bundle
- 不同皮肤的图片文件保存在不同的 Bundle 中。
- 问题:平面设计师维护不方便。
-
解决方案3:利用文件夹(蓝色)
- 不同皮肤的图片文件保存在不同的文件夹中。
- 好处:便于平面设计师维护。
此外,将用户上次使用的皮肤保存在用户偏好中,以便下次启动应用时能显示之前选中的皮肤。
2. 可能遇到的问题
问题一:默认没有皮肤颜色
解决方法:手动设置默认皮肤颜色。
if (_skinColor == nil) {
_skinColor = @"blue";
}
问题二:用户选中皮肤后,下次打开显示之前选中的皮肤
解决方法:将用户上次使用的皮肤保存在用户偏好中。
+ (void)setSkinColor:(NSString *)skinColor {
_skinColor = skinColor;
// 记录用户选中的皮肤
[[NSUserDefaults standardUserDefaults] setObject:skinColor forKey:skinColorKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
// 取出用户之前选中的皮肤
_skinColor = [[NSUserDefaults standardUserDefaults] objectForKey:skinColorKey];
问题三:图片命名不规范
解决方法:拷贝图片时用真实的文件夹,每种颜色的文件夹名用颜色名来命名。
+ (UIImage *)skinToolWithImageName:(NSString *)imageName {
NSString *imageNamePath = [NSString stringWithFormat:@"skin/%@/%@", _skinColor, imageName];
return [UIImage imageNamed:imageNamePath];
}
问题四:多控制器的换肤功能
解决方法:在 viewWillAppear:
方法中写换肤相关的代码,使换肤在多个控制器中生效。
3. 工具类封装
SkinTool.h
#import <UIKit/UIKit.h>
@interface SkinTool : NSObject
+ (void)setSkinColor:(NSString *)skinColor;
+ (UIImage *)skinToolWithImageName:(NSString *)imageName;
+ (UIColor *)skinToolWithLabelBgColor;
@end
SkinTool.m
#import "SkinTool.h"
NSString *const skinColorKey = @"skinColor";
@implementation SkinTool
static NSString *_skinColor;
+ (void)initialize {
_skinColor = [[NSUserDefaults standardUserDefaults] objectForKey:skinColorKey];
if (_skinColor == nil) {
_skinColor = @"blue";
}
}
+ (void)setSkinColor:(NSString *)skinColor {
_skinColor = skinColor;
[[NSUserDefaults standardUserDefaults] setObject:skinColor forKey:skinColorKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
+ (UIImage *)skinToolWithImageName:(NSString *)imageName {
NSString *imageNamePath = [NSString stringWithFormat:@"skin/%@/%@", _skinColor, imageName];
return [UIImage imageNamed:imageNamePath];
}
+ (UIColor *)skinToolWithLabelBgColor {
NSString *bgColorFileName = [NSString stringWithFormat:@"skin/%@/BgColor.plist", _skinColor];
NSString *bgColorFilePath = [[NSBundle mainBundle] pathForResource:bgColorFileName ofType:nil];
NSDictionary *bgColorDict = [NSDictionary dictionaryWithContentsOfFile:bgColorFilePath];
NSString *bgColorString = bgColorDict[@"LabelBgColor"];
NSArray *bgColorArray = [bgColorString componentsSeparatedByString:@","];
NSInteger red = [bgColorArray[0] integerValue];
NSInteger green = [bgColorArray[1] integerValue];
NSInteger blue = [bgColorArray[2] integerValue];
return [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0];
}
@end
4. 使用示例
设置橘色皮肤:
- (IBAction)switchOrangeSkin {
[SkinTool setSkinColor:@"orange"];
[self switchSkinImages];
}
- (void)switchSkinImages {
self.faceImageView.image = [SkinTool skinToolWithImageName:@"face"];
self.heartImageView.image = [SkinTool skinToolWithImageName:@"heart"];
self.rectImageView.image = [SkinTool skinToolWithImageName:@"rect"];
self.testLabel.backgroundColor = [SkinTool skinToolWithLabelBgColor];
}
在其他控制器中:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.faceImageView.image = [SkinTool skinToolWithImageName:@"face"];
self.heartImageView.image = [SkinTool skinToolWithImageName:@"heart"];
self.label.backgroundColor = [SkinTool skinToolWithLabelBgColor];
}
二、静态库
1. 简介
库是程序代码的集合,是共享程序代码的一种方式。根据源代码的公开情况,库可以分为两种:
- 开源库:公开源代码,如 SDWebImage、AFNetworking。
- 闭源库:不公开源代码,看不到具体实现。分为静态库和动态库。
2. 静态库和动态库
静态库和动态库的形式分别是:
- 静态库:
.a
和.framework
- 动态库:
.dylib
和.framework
静态库在链接时被复制到可执行文件中,而动态库在程序运行时由系统动态加载到内存中。需要特别注意的是,项目中如果使用了自制的动态库,不能被上传到 App Store。
三、静态库的制作和使用
1. 为什么要做静态库
静态库在保护核心技术和代码复用中有很大作用。例如国内的百度地图、友盟等提供的 SDK 就是静态库形式。动态库由于安全性和发布限制,多数情况下,我们会选择静态库。
2. 制作静态库的步骤
- 新建一个项目,如
Tools
。 - 创建一个类并实现简单的加法方法。
- 编译项目,分别为真机(arm)和模拟器(i386/x86_64)生成静态库。
- 将生成的
.a
文件和头文件拖入需要使用的项目中。
3. 静态库中的资源包使用
为了避免与主项目资源冲突,静态库中的图片资源可以使用 bundle。
- 创建一个 Bundle,并将图片资源添加其中。
- 创建一个类方法返回图片。
- 编译项目时会生成相应的 bundle 文件,在使用时需要将
.h
、.a
和XXX.bundle
一同导入。
4. 调试和发布版本
静态库有调试(Debug)和发布(Release)版本,调试版本包含完整的符号信息,未经过优化。发布版本则经过优化,体积更小,运行速度更快。在调试阶段使用 Debug 版,在发布阶段使用 Release 版。
5. 合并静态库
合并不同架构的静态库,以便在不同设备上使用:
lipo -create Debug-iphoneos/libTools.a Debug-iphonesimulator/libTools.a -output libTools.a
合并后的静态库会整合所有架构,利于调试和发布。
四、CPU架构
1. 常见报错
如果使用静态库时报错 Undefined symbols for architecture i386
,说明静态库不支持该 CPU 架构。
2. CPU 架构列表
- 模拟器架构:
- iPhone 4s 到 iPhone 5:
i386
- iPhone 5s 到 当前机型:
x86_64
- iPhone 4s 到 iPhone 5:
- 真机场构:
- iPhone 3GS 到 iPhone 4s:
armv7
- iPhone 5 到 iPhone 5c:
armv7s
- iPhone 5s 到 当前机型:
arm64
- iPhone 3GS 到 iPhone 4s:
3. 检查静态库支持架构
lipo -info libExample.a
五、创建和使用静态库时的注意点
- 制作
.a
静态库时需包含头文件。 - 新建项目,添加静态库 target 进行调试。
- 编译过程中关注选择合适的 CPU 架构和适当的调试版本。
- 编译出来的静态库通过选择合适配置支持多种设备和 CPU 架构。
结语
本文详细介绍了如何实现 iOS 应用的换肤功能以及静态库的制作和使用。通过这些技巧,我们能够更好地管理和优化代码,提高项目的复用性和用户体验。