iOS开发基础57-换肤功能与静态库开发指南

一、iOS 换肤功能

1. 换肤功能的思路

实现换肤功能的几点思路:

  1. 解决方案1:基于颜色的图片命名规范

    • 问题1:每套图片的文件名必须遵循“颜色+名称.png”格式。
    • 问题2:如果将某一图片应用到其他皮肤时会比较麻烦。
  2. 解决方案2:利用 Bundle

    • 不同皮肤的图片文件保存在不同的 Bundle 中。
    • 问题:平面设计师维护不方便。
  3. 解决方案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. 制作静态库的步骤

  1. 新建一个项目,如 Tools
  2. 创建一个类并实现简单的加法方法。
  3. 编译项目,分别为真机(arm)和模拟器(i386/x86_64)生成静态库。
  4. 将生成的 .a 文件和头文件拖入需要使用的项目中。

3. 静态库中的资源包使用

为了避免与主项目资源冲突,静态库中的图片资源可以使用 bundle。

  1. 创建一个 Bundle,并将图片资源添加其中。
  2. 创建一个类方法返回图片。
  3. 编译项目时会生成相应的 bundle 文件,在使用时需要将 .h.aXXX.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 3GS 到 iPhone 4s:armv7
    • iPhone 5 到 iPhone 5c:armv7s
    • iPhone 5s 到 当前机型:arm64

3. 检查静态库支持架构

lipo -info libExample.a

五、创建和使用静态库时的注意点

  1. 制作 .a 静态库时需包含头文件。
  2. 新建项目,添加静态库 target 进行调试。
  3. 编译过程中关注选择合适的 CPU 架构和适当的调试版本。
  4. 编译出来的静态库通过选择合适配置支持多种设备和 CPU 架构。

结语

本文详细介绍了如何实现 iOS 应用的换肤功能以及静态库的制作和使用。通过这些技巧,我们能够更好地管理和优化代码,提高项目的复用性和用户体验。

posted @ 2015-09-28 19:58  Mr.陳  阅读(1166)  评论(1编辑  收藏  举报