您的位置:首页 > 移动开发 > IOS开发

iOS开发——高级篇——换肤、静态库

2015-09-28 19:58 501 查看

一、换肤

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时一定注意版本


四、CPU架构

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⽂件下面的二进制

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: