iOS 实现快速切换主题详细教程(附上源码)
前言
iOS 实现主题切换,相信在未来的app里也是会频繁出现的,尽管现在只是出现在主流的APP,如(QQ、新浪微博、酷狗音乐、网易云音乐等),但是现在是看颜值、追求个性的年代,所以根据用户喜好自定义/切换主题也是未来app的必备功能了。
实现思路
为了降低耦合度,决定采用的方案是使用NSObject的分类来实现主题设置,有些读者可能会想为何不使用UIView的分类而是使用NSObject的分类?建议这部分读者看一下UIBarItem父类,然后仔细思考一下,就会理解了。
设置主题色

PYThemeColor.png
创建主题色池
将需要设置主题色的控件及其对应属性/方法添加到主题色池中
调用设置主题色方法时,遍历主题色池中的控件,使用KVC设置对应属性或调用对应的方法来实现主题色的设置
代码实现
建议读者在理解思路以后先下载源码大概看一下(纵观全局)再阅读以下内容:
源码地址:https://github.com/iphone5solo/PYTheme
1. 创建主题色池
由于是在NSObject的分类里面创建,为了方便管理,设置全局变量_themeColorPool,并通过懒加载完成_themeColorPool的实例化。数组中的对象采用为NSDictionary的原因见下一步就会理解了
|
1
2
3
4
5
6
7
8
9
10
11
|
/** 主题颜色池 */static NSMutableArray *_themeColorPool;#pragma mark - 懒加载- (NSMutableArray *)themeColorPool{ if (!_themeColorPool) { _themeColorPool = [NSMutableArray array]; } return _themeColorPool;} |
2. 添加控件到主题色池中
由于颜色设置有的可以直接通过属性设置也有的需要通过调用方法才可设置。以UIButton为例,设置背景色可通过属性button.backgroundColor设置,设置选中状态时的字体颜色则要调用setTitleColor:forState:方法才可设置,于是,就得提供两个方法供使用者调用,如下
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * 添加到主题色池 * selector : 执行方法 * objects : 方法参数数组 * 注意:方法参数必须按顺序一一对应,如果涉及到的主题色设置使用 PYTHEME_THEME_COLOR 宏定义代替 * 如果数组中某个参数为nil,需包装为 [NSNull null] 对象再添加到数组中 */- (void)py_addToThemeColorPoolWithSelector:(SEL)selector objects:(NSArray *)objects;/** * 添加到主题色池 * propertyName : 属性名 */- (void)py_addToThemeColorPool:(NSString *)propertyName; |
实现如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#pragma mark - Theme Color/** * 添加到主题色池 * selector : 执行方法 * objects : 方法参数数组 * 注意:方法参数必须按顺序一一对应,如果涉及到的主题色设置使用 PYTHEME_THEME_COLOR 宏定义代替 * 如果数组中某个参数为nil,需包装为 [NSNull null] 对象再添加到数组中 */- (void)py_addToThemeColorPoolWithSelector:(SEL)selector objects:(NSArray *)objects{ // 判断参数是否为空 if (!objects) return; Class appearanceClass = NSClassFromString(@"_UIAppearance"); // 如果对象为_UIAppearance,直接返回 if ([self isMemberOfClass:appearanceClass]) return; // 键:对象地址+方法名 值:对象 NSString *pointSelectorString = [NSString stringWithFormat:@"%p%@", self, NSStringFromSelector(selector)]; NSDictionary *dic = @{ pointSelectorString : self, PYTHEME_COLOR_ARGS_KEY : objects }; // 判断是否已经在主题色池中 if (![[self themeColorPool] containsObject:dic]) { // 不在主题色池中 [[self themeColorPool] addObject:dic]; if (_currentThemeColor) { // 已经设置主题色,直接设置 [self py_performSelector:selector withObjects:objects]; } }}/** * 添加到主题色池 * propertyName : 属性名 */- (void)py_addToThemeColorPool:(NSString *)propertyName{ // 如果对象为_UIAppearance,直接返回 Class appearanceClass = NSClassFromString(@"_UIAppearance"); if ([self isMemberOfClass:appearanceClass]) return; // 键:对象地址+属性名 值:对象 NSString *pointString = [NSString stringWithFormat:@"%p%@", self, propertyName]; NSDictionary *dic = @{ pointString : self }; // 判断是否已经在主题色中 if (![[self themeColorPool] containsObject:dic]) { // 不在主题色池中 [[self themeColorPool] addObject:dic]; if (_currentThemeColor) { // 已经设置主题色,直接设置 [self setValue:_currentThemeColor forKey:propertyName]; } } // 遍历主题色池(移除应该被回收的对象) for (NSDictionary *dict in [[self themeColorPool] copy]) { // 取出key NSString *objectKey = nil; for (NSString *key in [dict allKeys]) { if (![key isEqualToString:PYTHEME_COLOR_ARGS_KEY]) { objectKey = key; break; } } // 取出对象 id object = [dict valueForKey:objectKey]; // 取出对象的引用计数 NSInteger retainCount = [[object valueForKey:@"retainCount"] integerValue]; if (retainCount == 2) { // 对象应该被回收了 [[self themeColorPool] removeObject:dict]; } }} |
为了满足个别需求,所以还是提供一下从主题色池中移除控件的方法
|
1
2
3
4
5
6
7
8
9
10
|
/** * 从主题色池移除 * propertyName : 属性名 */- (void)py_removeFromThemeColorPool:(NSString *)propertyName;/** * 从主题色池移除 * selector : 方法选择器 */- (void)py_removeFromThemeColorPoolWithSelector:(SEL)selector; |
实现如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
/** * 从主题色池移除 * propertyName : 属性名 */- (void)py_removeFromThemeColorPool:(NSString *)propertyName{ // 如果对象为_UIAppearance,直接返回 Class appearanceClass = NSClassFromString(@"_UIAppearance"); if ([self isMemberOfClass:appearanceClass]) return; // 键:对象地址+属性名 值:对象 NSString *pointString = [NSString stringWithFormat:@"%p%@", self, propertyName]; NSDictionary *dic = @{ pointString : self }; // 判断是否已经在主题色池中 if ([[self themeColorPool] containsObject:dic]) { // 在主题色池中 [[self themeColorPool] removeObject:dic]; }}/** * 从主题色池移除 * selector : 方法选择器 */- (void)py_removeFromThemeColorPoolWithSelector:(SEL)selector{ // 如果对象为_UIAppearance,直接返回 Class appearanceClass = NSClassFromString(@"_UIAppearance"); if ([self isMemberOfClass:appearanceClass]) return; // 键:对象地址+方法名 NSString *pointSelectorString = [NSString stringWithFormat:@"%p%@", self, NSStringFromSelector(selector)]; // 遍历主题色池(移除应该被回收的对象) for (NSDictionary *dict in [[self themeColorPool] copy]) { for (NSString *key in [dict allKeys]) { if ([key isEqualToString:pointSelectorString]) { // 存在,移除 [[self themeColorPool] removeObject:dict]; return; } } }} |
3. 设置主题色
实现如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/** * 设置主题色 * color : 主题色 */- (void)py_setThemeColor:(UIColor *)color{ _currentThemeColor = color; // 遍历缓主题池,设置统一主题色 for (NSDictionary *dict in [_themeColorPool copy]) { // 取出key NSString *objectKey = nil; for (NSString *key in [dict allKeys]) { if (![key isEqualToString:PYTHEME_COLOR_ARGS_KEY]) { objectKey = key; break; } } // 取出对象 id object = [dict valueForKey:objectKey]; if ([objectKey containsString:@":"]) { // 方法 // 取出参数 NSArray *args = dict[PYTHEME_COLOR_ARGS_KEY]; // 取出方法 NSString *selectorName = [objectKey substringFromIndex:[[NSString stringWithFormat:@"%p", object] length]]; SEL selector = NSSelectorFromString(selectorName); // 调用方法,设置属性 [object py_performSelector:selector withObjects:args]; } else { // 成员属性 // 取出属性值 NSString *propertyName = [objectKey substringFromIndex:[[NSString stringWithFormat:@"%p", object] length]]; // 给对象的对应属性赋值(使用KVC) [object setValue:color forKeyPath:propertyName]; } }} |
使用
假设有个需求:UINavigationBar的背景颜色和UIButton选中时的字体颜色会随着主题颜色的变化而变化,实现如下:
将navigationBar的background和UIButton的setTitleColor:forState:方法添加到主题池中,方法参数中如果是设置为主题色的参数则用PYTHEME_THEME_COLOR占位,如果参数为nil,则使用[NSNull null]代替
|
1
2
3
4
5
6
7
8
9
|
// 创建导航栏UINavigationBar *navigationBar = [[UINavigationBar alloc] init];// 添加到主题色池中[navigationBar py_addToThemeColorPool:@"barTintColor"];// 创建按钮UIButton *button = [[UIButton alloc] init];// 添加到主题色中[button py_addToThemeColorPoolWithSelector:@selector(setTitleColor:forState:) objects:@[PYTHEME_THEME_COLOR, @(UIControlStateSelected)]]; |
设置主题色
|
1
2
|
// 设置主题色为红色[self py_setThemeColor:[UIColor redColor]]; |
这里有一点注意的是[object py_performSelector:selector withObjects:args];这是自己实现的performSelector 多参调用关于这方面的网上已经有很多教程了,这里就不多介绍了。直接附上的我实现(内部方法,主要考虑到自己的使用):
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#pragma mark - performSelector 多参调用- (id)py_performSelector:(SEL)selector withObjects:(const NSArray *)objects{ // 1. 创建方法签名 // 根据方法来初始化NSMethodSignature NSMethodSignature *methodSignate = [[self class] instanceMethodSignatureForSelector:selector]; if (!methodSignate) { // 没有该方法 return self; } // 2. 创建invocation对象(包装方法) NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignate]; // 3. 设置相关属性 // 调用者 invocation.target = self; // 调用方法 invocation.selector = selector; // 获取除self、_cmd的参数个数 NSInteger paramsCount = methodSignate.numberOfArguments - 2; // 取最少的,防止越界 NSInteger count = MIN(paramsCount, objects.count); // 用于dictionary的拷贝(用于保住objCopy,避免非法内存访问) NSMutableDictionary *objCopy = nil; // 设置参数 for (int i = 0; i < count; i++) { // 取出参数对象 id obj = objects[i]; // 如果是主题颜色参数颜色,则设置 if ([obj isKindOfClass:[NSString class]] && [obj isEqualToString:PYTHEME_THEME_COLOR]) { obj = _currentThemeColor; } // 判断需要设置的参数是否是NSNull, 如果是就设置为nil if ([obj isKindOfClass:[NSNull class]]) { obj = nil; } // 获取参数类型 const char *argumentType = [methodSignate getArgumentTypeAtIndex:i + 2]; // 判断参数类型 根据类型转化数据类型(如果有必要) NSString *argumentTypeString = [NSString stringWithUTF8String:argumentType]; if ([argumentTypeString isEqualToString:@"@"]) { // id // 如果是dictionary,可能存在 PYTHEME_THEME_COLOR if ([obj isKindOfClass:[NSDictionary class]]) { // NSDictionary objCopy = [obj mutableCopy]; // 取出所有键 NSArray *keys = [objCopy allKeys]; for (NSString *key in keys) { // 取出值 id value = objCopy[key]; if ([value isKindOfClass:[NSString class]] && [value isEqualToString:PYTHEME_THEME_COLOR]) { // 替换成颜色 [objCopy setValue:_currentThemeColor forKey:key]; } } [invocation setArgument:&objCopy atIndex:i + 2]; } else { // 其他 [invocation setArgument:&obj atIndex:i + 2]; } } else if ([argumentTypeString isEqualToString:@"B"]) { // bool bool objVaule = [obj boolValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"f"]) { // float float objVaule = [obj floatValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"d"]) { // double double objVaule = [obj doubleValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"c"]) { // char char objVaule = [obj charValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"i"]) { // int int objVaule = [obj intValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"I"]) { // unsigned int unsigned int objVaule = [obj unsignedIntValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"S"]) { // unsigned short unsigned short objVaule = [obj unsignedShortValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"L"]) { // unsigned long unsigned long objVaule = [obj unsignedLongValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"s"]) { // shrot short objVaule = [obj shortValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"l"]) { // long long objVaule = [obj longValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"q"]) { // long long long long objVaule = [obj longLongValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"C"]) { // unsigned char unsigned char objVaule = [obj unsignedCharValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"Q"]) { // unsigned long long unsigned long long objVaule = [obj unsignedLongLongValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"{CGRect={CGPoint=dd}{CGSize=dd}}"]) { // CGRect CGRect objVaule = [obj CGRectValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } else if ([argumentTypeString isEqualToString:@"{UIEdgeInsets=dddd}"]) { // UIEdgeInsets UIEdgeInsets objVaule = [obj UIEdgeInsetsValue]; [invocation setArgument:&objVaule atIndex:i + 2]; } } // 4.调用方法 [invocation invoke]; // 5. 设置返回值 id returnValue = nil; if (methodSignate.methodReturnLength != 0) { // 有返回值 // 将返回值赋值给returnValue [invocation getReturnValue:&returnValue]; } return returnValue;} |
细节处理
1. 设置主题色的方式
通过属性直接设置主题色
通过调用方法并以主题色为参数来设置主题色
通过调用方法但主题色被封装后(如:NSDictionary)作为参数设置主题色
2. 自动管理内存管理
当对象应该被释放后,下一次当主题色池有新元素添加时,会遍历主题色池,根据对象的引用计数来决定是否移除对象(实现自动管理内存),因此:主题色池中最多可能会残留一个对象,这对内存几乎没有任何影响,如果要及时释放对象本人认为可以采用KVO监听对象的引用计数(未尝试),但是耗能高,不建议这么做!
3. 当对象为_UIAppearance类时,不添加到主题色池
了解UIAppearance的读者应该可以理解,而且使用UIAppearance的目的也为为了设置全局色,所以为了避免冲突,如果使用了该“技术”就不添加到主题色池
设置主题图片
观察了新浪微博、酷狗音乐等app,发现设置主题图片还是很有必要的,而且发现每套主题皮肤/图片都有对应的主题色,所以在设计接口的时候都考虑了这方面的需求。先看一下设置主题图片的基本原理,如下:
创建一个主题图片池(使用懒加载)
将相关控件对象直接添加到主题图片池中
设置主题图片时,通过block把主题图片池中的所有对象传递给用户,用户实现block,在block中获得对象,并根据需求设置相关属性完成主题图片的设置
代码实现:
1. 创建一个主题图片池(使用懒加载)
|
1
2
3
4
5
6
7
8
9
10
|
/** 主题图片池 */static NSMutableArray(id) *_themeImagePool;(此处圆括号代替尖括号)- (NSMutableArray *)themeImagePool{ if (!_themeImagePool) { _themeImagePool = [NSMutableArray array]; } return _themeImagePool;} |
2. 添加相关控件到主题图片池中
因为在设置图片是,比较复杂,如UITabBar上面的UIBarItem的图片、字体颜色等,所以为了满足大部分用户的需求,决定采用的是直接存储控件对象
|
1
2
3
4
5
|
/** 添加到主题图片池 */- (void)py_addToThemeImagePool;/** 从主题图片池中移除 */- (void)py_removeFromThemeImagePoo |
实现如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#pragma mark - Theme Image/** 添加到主题图片池 */- (void)py_addToThemeImagePool{ // 如果对象为_UIAppearance,直接返回 Class appearanceClass = NSClassFromString(@"_UIAppearance"); if ([self isMemberOfClass:appearanceClass]) return; if ([self isKindOfClass:[UITabBarItem class]]) { // 如果是UITabBarItem,判断是否有设置图片 UITabBarItem *item = (UITabBarItem *)self; if (!item.image) { // 没有设置图片 item.image = [[UIImage alloc] init]; } if (!item.selectedImage) { // 没有设置图片 item.selectedImage = [[UIImage alloc] init]; } } // 判断是否已经在主题图片池中 if (![[self themeImagePool] containsObject:self]) { // 不在主题图片池中 [[self themeImagePool] addObject:self]; } // 遍历主题图片池(移除应该被回收的对象) for (id object in [self themeImagePool]) { NSInteger retainCount = [[object valueForKey:@"retainCount"] integerValue]; if (retainCount == 2) { // 对象应该被回收了 [[self themeImagePool] removeObject:self]; } }}/** 从主题图片池中移除 */- (void)py_removeFromThemeImagePool{ // 如果对象为_UIAppearance,直接返回 Class appearanceClass = NSClassFromString(@"_UIAppearance"); if ([self isMemberOfClass:appearanceClass]) return; // 判断是否已经在图片池中 if ([[self themeImagePool] containsObject:self]) { // 在主题图片池中 [[self themeImagePool] removeObject:self]; }} |
3. 设置主题图片和相关配色
当设置图片时,会通过block将主题图片池里面的所有控件传递给用户,用户根据需求进行相关设置,如果提供了配色,就会采用上面设置主题色功能来设置主题色
|
1
2
3
4
5
6
|
/** * 重新加载主题图片 * themeColor : 主题色 * block : 设置主题图片时调用的block */- (void)py_reloadThemeImageWithThemeColor:(UIColor *)themeColor setting:(PYThemeImageSettingBlock)block; |
实现如下:
|
1
2
3
4
5
6
7
8
9
10
11
|
/** 重新加载主题图片 */- (void)py_reloadThemeImageWithThemeColor:(UIColor *)themeColor setting:(PYThemeImageSettingBlock)block{ if (themeColor) { // 有主题色,设置主题色 [self py_setThemeColor:themeColor]; } if (block) { // 存在block,直接调用 block([self themeImagePool]); }} |
使用
假设现在有这么一个需求:更换主题图片时,更换UITabBarItem的图片
1.将UITabBarItem添加到图片池
|
1
2
|
// UITabBarItem[childController.tabBarItem py_addToThemeImagePool]; |
2.切换主题图片并设置配色为红色
|
1
2
3
4
|
// 重新加载主题图片,并设置主题色为红色[self py_reloadThemeImageWithThemeColor:[UIColor redColor] setting:^(const NSArray *objects) { // 根据控件类型完成相关设置} |
总结
篇幅可能有点大,能耐心读到这里的读者相信会有不少收获的,希望读者在阅读此教程的时候,千万不要学习代码实现,而是要多思考:为什么要这样实现?那样实现有什么不好?多学学接口为什么要这样设计,那样设计是不是更合理?当你带着这些问题再回过头来去看看源码时,希望你会有更多的收货!当然,这里只是提供了一种思路,你也可以在此基础上实现夜间模式的切换等。期待你们的实现!
期望
当然如果您有更多的想法想表达或者交流的话,欢迎到留言/评论!因为本人比较喜欢活跃在GitHub社区,所以,如果您有什么想反馈的也可以issuse me,在这也鼓励大家去多多发现优秀源码,并且共享给大家。毕竟分享是双方获利的,何乐而不为?
源码地址:https://github.com/iphone5solo/PYTheme
iOS 实现快速切换主题详细教程(附上源码)的更多相关文章
- PHP PC端微信扫码支付【模式二】详细教程-附带源码(转)
博主写这破玩意儿的时候花了大概快两天时间才整体的弄懂逻辑,考虑了一下~还是把所有代码都放出来给大家~抱着开源大无私的精神!谁叫我擅长拍黄片呢?同时也感谢我刚入行时候那些无私帮过我的程序员们! 首先还是 ...
- easyUI整合富文本编辑器KindEditor详细教程(附源码)
原因 在今年4月份的时候写过一篇关于easyui整合UEditor的文章Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合,从那 ...
- 史上最详细的IDEA优雅整合Maven+SSM框架(详细思路+附带源码)
目录 前言: 1. 搭建整合环境 2.Spring框架代码的编写 3.SpringMVC框架代码的编写 4. Spring整合SpringMVC的框架 5.MyBatis框架代码的编写 6. Spri ...
- LIRE教程之源码分析 | LIRE Tutorial of Analysis of the Source Code
LIRE教程之源码分析 |LIRE Tutorial of Analysis of the Source Code 最近在做地理图像识别和检索的研究,发现了一个很好用的框架LIRE,遂研究了一通.网上 ...
- 使用 IDEA 创建 SpringBoot 项目(详细介绍)+ 源码案例实现
使用 IDEA 创建 SpringBoot 项目 一.SpringBoot 案例实现源码 二.SpringBoot 相关配置 1. 快速创建 SpringBoot 项目 1.1 新建项目 1.2 填写 ...
- PHP简单的长文章分页教程 附源码
PHP简单的长文章分页教程 附源码.本文将content.txt里的内容分割成3页,这样浏览起来用户体验很好. 根据分页参数ipage,获取对应文章内容 include('page.class.php ...
- GEF入门实例_总结_01_教程、源码、开发环境准备
一.前言 最近在学Eclipse插件开发,发现了一个比较好的GEF入门教程,并且按照教程上的操作,一步步实现了一个入门Demo,在此感谢作者的贡献. 好记性不如烂笔头,故决定总结一下这段时间的学习心得 ...
- SpringBoot 项目搭建(详细介绍+案例源码)
SpringBoot 项目搭建 SpringBoot 项目整合源码 SpringBoot 项目整合 一.项目准备 1.1 快速创建 SpringBoot 项目 1.2 标准项目结构图如下 1.3 添加 ...
- vim一个快速切换主题的插件(change-colorscheme,原创)
概述 有时候我们想快速浏览主题并找到一款合适的主题,change-colorscheme将会满足我们的要求. 安装 git https://github.com/chxuan/change-color ...
随机推荐
- Lintcode 175 Invert Binary Tree
I did it in a recursive way. There is another iterative way to do it. I will come back at it later. ...
- 打包解决方案后,安装时提示只能在IIS5.1以上运行解决方法
环境:vs2010 sp1,mvc4,WIN10 生成安装项目后进行安装提示: 此安装程序需要Internet Information Server 5.1或更高版本和Windows XP和更高的安装 ...
- protobuf-net 与 C#中几种序列化的比较
C#中几种序列化的比较,此次比较只是比较了 序列化的耗时和序列后文件的大小. 几种序列化分别是: 1. XmlSerializer 2. BinaryFormatter 3. DataContract ...
- Html5前端框架
BootCss bootcss.com amazeui http://amazeui.org/
- 基于Qt的流程设计器(一)
一: 先来看一下界面的截图: 说明: 拖动节点的时候,与该节点相关的箭头连线也会跟着调整: 用户可以使用鼠标从一个节点拖出一个箭头到另一个节点(鼠标在空白区域点击一下,拖出的箭头消失) 这三个 ...
- fgets函数执行完成后,文件指针如何移动?
用fgets执行之后,读取了文件中的一行,这时文件位置指针是自动指向文件的下一行的开头吗,还是指向当前行的结尾?如果一行的字符串没读取完会怎样? 实例结果: 如果一行的字符串没读取完会,下一次会接着上 ...
- paip.语义分析--单字动词表.txt
paip.语义分析--单字动词表.txt 排除重复 select * from t where word in (SELECT word from t_a) or word in (SELEC ...
- iOS-SVN、Git
版本控制SVN和Git使用详解 公司的实际开发中,在天朝使用较多的还是SVN,因为SVN是集中式的,在天朝上班你们都懂的! -----------------svn--------- ...
- 好消息!Html5游戏和动画的福音
今年基本都淡出了cocos2d-js的开发,更多集中在普通H5应用上,还有自己的Fanvas组件(http://code.tencent.com/),做canvas动画. 不过,最近回头一看WebGL ...
- 建立一个名叫Cat的类
//属性 成员变量 String name; int age; String color; //方法 函数 成员函数 void name() { System.out.println("名字 ...