1、思路
1> 解决方案1,使用颜色作为图片素材的命名关键字
问题1:要保证每套图片的文件名 颜色+ 名称.png的格式比较麻烦
问题2:如果要将某一个图片应用到其他皮肤不方便
2> 解决方案2,利用Bundle,将图片文件保存在不同的Bundle中
问题:平面设计师维护不方便
3> 解决方案3,利用文件夹(蓝色),将图片文件保存在不同文件夹中
好处:便于平面设计师针对不同的文件夹维护图片素材
扩展,将用户上次使用的皮肤保存在用户偏好中
2、可能遇到的问题
问题一:默认进来是没有皮肤颜色
解决方案:手动设置
// 判断skinColor是否为空,如果为空,表示用户之前没有选中皮肤,那么显示蓝色皮肤 if (_skinColor == nil) { _skinColor = @"blue"; } }
问题二:当用户选中某一个皮肤,下次打开程序,应该依然显示之前选中的皮肤
解决方案:将用户上次使用的皮肤保存在用户偏好中
/** * 设置当前选中的皮肤 */ + (void)setSkinColor:(NSString *)skinColor { _skinColor = skinColor; // 记录用户选中的皮肤 [[NSUserDefaults standardUserDefaults] setObject:skinColor forKey:skinColor]; [[NSUserDefaults standardUserDefaults] synchronize]; } // 先从偏好设置中取出用户之前选中的皮肤 再判断skinColor是否为空 _skinColor = [[NSUserDefaults standardUserDefaults] objectForKey:skinColor];
问题三:美工给我们的图片,可能不是像这种:red_face,颜色不同的相同图片命名完全一样
解决方案:拷贝图片时用真实的文件夹(蓝色的),每一种颜色的文件夹名用颜色名来命名
/** * 根据用户选择皮肤后设置对应的背景图片 */ + (UIImage *)skinToolWithImageName:(NSString *)imageName { NSString *imageNamePath = [NSString stringWithFormat:@"skin/%@/%@", _skinColor, imageName]; return [UIImage imageNamed:imageNamePath]; }
问题四:多控制器换肤功能(切换皮肤之后,多个控制器都实现换肤)
解决方案:在viewWillAppear:方法中写换肤相关的代码
3、工具类(具体代码)
.h
#import <UIKit/UIKit.h> @interface SkinTool : NSObject /** * 设置当前选中的皮肤 */ + (void)setSkinColor:(NSString *)skinColor; /** * 根据用户选择皮肤后设置对应的背景图片 */ + (UIImage *)skinToolWithImageName:(NSString *)imageName; /** * 根据用户选择皮肤后设置label的背景颜色 */ + (UIColor *)skinToolWithLabelBgColor; @end
.m
#import "SkinTool.h" NSString *const skinColorKey = @"skinColor"; @implementation SkinTool static NSString *_skinColor; /** * 当类第一次使用的时候会调用该方法,该方法只会调用一次 */ + (void)initialize { // 1.先从偏好设置中取出用户之前选中的皮肤 _skinColor = [[NSUserDefaults standardUserDefaults] objectForKey:skinColorKey]; // 2.判断skinColor是否为空,如果为空,表示用户之前没有选中皮肤,那么显示蓝色皮肤 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]; } /** * 根据用户选择皮肤后设置label的背景颜色 */ + (UIColor *)skinToolWithLabelBgColor { // 1.找到对应背景的plist文件 NSString *bgColorFileName = [NSString stringWithFormat:@"skin/%@/BgColor.plist", _skinColor]; NSString *bgColorFilePath = [[NSBundle mainBundle] pathForResource:bgColorFileName ofType:nil]; // 2.加载背景颜色 // 2.1.加载背景字典 NSDictionary *bgColorDict = [NSDictionary dictionaryWithContentsOfFile:bgColorFilePath]; // 2.2.取出背景颜色的字符串 NSString *bgColorString = bgColorDict[@"LabelBgColor"]; // 2.3.取出背景颜色的数组(0,255,0) NSArray *bgColorArray = [bgColorString componentsSeparatedByString:@","]; // 2.4.取出对应的RGB值 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 { // 1.告诉工具类当前皮肤的颜色 [SkinTool setSkinColor:@"orange"]; // 2.切换对应皮肤的图片 [self switchSkinImages]; } - (void)switchSkinImages { self.faceImageView.image = [SkinTool skinToolWithImageName:@"face"]; self.heartImageView.image = [SkinTool skinToolWithImageName:@"heart"]; self.rectImageView.image = [SkinTool skinToolWithImageName:@"rect"]; // 切换Label的背景 self.testLabel.backgroundColor = [SkinTool skinToolWithLabelBgColor]; }
那么在其他控制器中只要在viewWillAppear方法中如下使用,注意凡是涉及到了换肤的代码都写这里
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // 注意:换肤的内容(背景图片/背景颜色/字体的大小),写在viewWillAppear方法 self.faceImageView.image = [SkinTool skinToolWithImageName:@"face"]; self.heartImageView.image = [SkinTool skinToolWithImageName:@"heart"]; self.label.backgroundColor = [SkinTool skinToolWithLabelBgColor]; }
1、简介
什么是库?
库是程序代码的集合,是共享程序代码的一种方式
根据源代码的公开情况,库可以分为2种类型
开源库
公开源代码,能看到具体实现
比如SDWebImage、AFNetworking
闭源库
不公开源代码,是经过编译后的二进制文件,看不到具体实现
主要分为:静态库、动态库
2、静态库和动态库
静态库和动态库的存在形式
静态库:.a 和 .framework
动态库:.dylib 和 .framework
静态库和动态库在使用上的区别
静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝(PPT左图所示)
动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存(PPT右图所示)
需要注意的是:
项目中如果使用了自制的动态库,不能被上传到AppStore
01. 为什么要做静态库
1> 国内的企业,掌握有核心技术,同时是又希望更多的程序员来使用其技术,因此采用"闭源"的方式开发使用
例如:百度地图,友盟,JPush等
2> 在企业开发中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,也会提供静态库给程序员使用
02. 静态库的特点
.a + .h
03. 静态库简单演练
1> 新建Tools项目
2> 创建一个类方法,实现一个简单的加法
3> 编译
# 注意,在编译静态库时,需要编译两个版本 -> 真机(arm) | 模拟器(i386)
4> 新建项目将编译生成的.a + .h拖到项目中使用
04. 静态库中的资源包的使用
问题:有些第三方库会使用到一些图片素材,例如公司的logo等。
但是由于Xcode默认在编译时会把所有的素材文件导入到mainBundle中,为了避免与使用静态库的程序冲突。
在静态库中如果要使用图片素材,会利用bundle的手段
1> 建立bundle,并且向其中添加图片
2> 创建一个类方法,返回图片
3> 编译
4> 调用方如果需要使用,需要导入 .h + .a + XXX.bundle
05. 静态库中的自定义视图
问题:程序需要测试
静态库如何测试呢?
创建复合项目
1> 复习块代码传值
06. 静态库的使用
新建项目将编译生成的.a + .h拖到项目中使用
07. 静态库的种类
静态库文件的版本(4种)
1.真机-Debug版本
2.真机-Release版本
3.模拟器-Debug版本
4.模拟器-Release版本
调试版本(Debug版本) VS 发布版本(Release版本)
- 调试版本会包含完整的符号信息,以方便调试
- 调试版本不会对代码进行优化
- 发布版本不会包含完整的符号信息
- 发布版本的执行代码是进行过优化的
- 发布版本的大小会比调试版本的略小
- 在执行速度方面,发布版本会更快些,但不意味着会有显著的提升
08. 静态库的合并
# 检测.a的类型
$ lipo -info libCZTools.a
# 合并.a
lipo -create Debug-iphoneos/libTools.a Debug-iphonesimulator/libTools.a -output libTools.a
# 合并.a的好处,开发过程中既可以在真机上调试,也可以在模拟器上调试
# 合并.a的坏处,如果静态库太大,合并打包后,会非常大,因此很多第三方的静态库的.a是区分版本的
# 今后在使用.a时一定注意版本
1、常见报错
如果发现使用静态库是报一下错误:
Undefined symbols for architecture i386: OBJC_CLASS_$_MathTool
说明你的静态库不支持 i386 这种CPU架构
2、CPU架构
每一个手机都有属于自己的CPU,而每一个CPU都有属于自己的CPU架构(指令集)
每一个静态库都有自己可以支持的架构
手机和模拟器使用的CPU架构
模拟器CPU架构
iPhone4s-->iphone5 : i386
iphone5s-->iphone6s plus : x86_64
真机CPU架构
iPhone3gs-->iphone4s : armv7
iphone5-->iphone5c : armv7s(如果一个静态库支持armv7架构,那么也可以跑在架构是armv7s的设备,没有对代码进行优化)
iPhone5s-->iPhone6s plus : arm64
查看静态库支持的架构:lipo -info 静态库名称
合并静态库:
lipo -create 静态库1 静态库2 -output 新的静态库
1.制作.a的静态库(Framework&Library) 需包含头?件(项目—>build Phase—>copy File—>选中头?文件)
2.边开发边制作静态库
添加一个静态库的targets—>点击项目—>targets—>+
测试静态库: 项目—>项目的target—>general—>linked framework—>添加静 态库
打包静态库—>选中项目静态库—>编译(头?件)
3.使?静态库的注意点:
静态库有真机和模拟器(测试阶段可以使?模拟器,发布阶段使?真机).好处:资源包变?
静态库有Debug版和release版本(测试阶段使用Debug,发布阶段使用release).好处:资源包变小/运行速度变快/代码进?优化
默认情况下资源打包上传到app 默认就是release版本的
编译出来的静态库,所有设备CPU的架构都能支持(选择NO,代表编译出来的静态库不仅仅只支持当前选中的设备CPU的构架):
4.制作.framework库
1>动态库(默认) 注意:如果项目中?到了动态库要先进?设置:项目—>项目的target—> general— >Embedded—>添加动态库
2>静态库 制作静态库的修改配置:项目—>静态库的target—>build setting—>搜索mach —>static library
3>注意点 查看?个.framework静态库?持哪些架构:lipo -info framework?件下面的二 进制 合并静态库:合并framework?件下面的二进制
原文:http://www.cnblogs.com/chglog/p/4844804.html