如何把设计图自动转换为iOS代码? 在线等,挺急的!
这是一篇可能略显枯燥的技术深度讨论与实践文章.如何把设计图自动转换为对应的iOS代码?作为一个 iOS开发爱好者,这是我很感兴趣的一个话题.最近也确实有了些许灵感,也确实取得了一点小成果,和大家分享一下.欢迎感兴趣的iOS爱好者能和我一起研究讨论!
这是一个可以节省 70% 工作量的话题
我觉得,如果真的能把一张设计图自动转换为代码,任何开发工程师都会感兴趣的.单以 iOS 应用为例, 在一个最常用的MVC架构的APP中,主要的代码,无非就是集中于: M 的网络请求部分, V的数据显示部分, C的逻辑交互部分.对于controller控制器层,往往需要结合业务逻辑去处理,代码量并不算大;对于Model数据模型层,我们有 AFNetworing, RestKit, MJExtension等,可以大大简化网络接口到数据模型的转换;对于View视图层,代码最繁杂,最枯燥无趣,迭代最让人头疼的部分,又有什么可以凭借呢?我没有详实的数据统计来确认各个iOS开发者的日常开发中,MVC各个层面,具体的时间成本如何;单从我个人角度来说, View布局的拆分与转换,占据了我 70% 以上的时间.我们公司通常是按单个完整任务来拆分工作的,单个任务的MVC三层,都是应该由一个人独立完成.每次都把大把时间浪费在"画UI"上,真的感觉好无趣,好浪费生命;临时遇到产品经理改动需求,可能一个对方看似更加"合理"的改动,我这边几乎要大动干戈!我想我对编程本身确实是感兴趣的,但是整天浪费时间在 UI上,真的感觉有点虚度光阴.所以说,在本不充裕的空闲里,我一直在思考的一个命题就是: 如何实现 UI 的自动化与独立化.
过往的尝试: 基于Xib的视图模块化.
尽管作为一名iOS开发人员,我依然对苹果公司提供的开发技术及其发展方向持谨慎和保守态度.前一段时间,尝试使用 Xib来布局视图,遇到一些坑,但是熟悉之后,也确实比原来单纯基于绝对位置的纯代码布局更灵活些,也更快捷些.在此期间,我研究的一个重要话题就是如何实现Xib之间的嵌套复用,即在一个Xib上如何直接嵌入另一个Xib.乍听起来很简单,但是在亲身实践之后,才发现其难度.我不是来吐槽的,个中曲折不再一一赘述,下面是我研究的成果:
上图,是一个Xib模块,其中的色块部分,嵌套的是另一个Xib模块.最终显示是,色块会自动被对应的Xib模块替代.
核心代码如下:
//
// MCComponent.h
// iOS122
//
// Created by 颜风 on 15/7/5.
// Copyright (c) 2015年 iOS122. All rights reserved.
//
#import "MCConstants.h"
/**
* 可复用组件.用于编写可嵌套的 xib 组件.
*
* 适用场景: 需要静态确定布局的页面内的UI元素的复用性问题.
* 使用方法: 在xib或storyboard中,将某一用于占位的view的 custom class 设为对一个的 component, 则初始化时,会自动使用此component对应的xib文件中的内容去替换对应位置.
* 注意: 对于可动态确定布局的部分,如tableView中的cell,直接自行从xib初始化即可,不必继承于 MCComponent.
*/
@interface MCComponent : UIView
@property (strong, nonatomic) UIView * contentView; //!< 真正的内容视图.
@property (weak, nonatomic, readonly) UIViewController * viewController; //!< 当前视图所在的控制器.
@property (weak, nonatomic, readonly)NSLayoutConstraint * heightContronstraint; //!< 高度的约束.不存在,则返回nil.
@property (strong, nonatomic) id virtualModel; //!< 虚拟model.用于测试.默认返回nil.当不为nil,优先使用它.
@property (strong, nonatomic) id model; //!< 视图数据模型.内部会自动根据virtualModel的值,进行不同的处理.
@property (assign, nonatomic, readonly) BOOL isTest; //!< 是否是测试.如果是,将优先使用 virtualModel来替换model.系统内部处理.默认为NO.
/**
* 初始化.
*
* 子类需要继承此方法,以完成自定义初始化操作. 不要手动调用此方法.
*/
- (void)setup;
/**
* 重新加载数据.
*
* 子类可根据需要,具体实现此方法.
*/
- (void)reloadData;
/**
* 返回上一级.
*/
- (void) back;
/**
* 便利构造器.子类应根据需要重写.
*
* @return 默认返回self.
*/
+ (instancetype)sharedInstance;
/**
* 更新视图.
*
* 子类应根据需要重写此方法.默认不做任何处理.
*/
- (void) updateView;
@end
//
// MCComponent.m
// iOS122
//
// Created by 颜风 on 15/7/5.
// Copyright (c) 2015年 iOS122. All rights reserved.
//
#import "MCComponent.h"
@interface MCComponent ()
@end
@implementation MCComponent
@dynamic virtualModel;
@synthesize model = _model;
- (instancetype)init
{
self = [super init];
if (nil != self) {
[self mcSetup: NO];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame: frame];
if (nil != self) {
[self mcSetup: NO];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (nil != self) {
[self mcSetup: YES];
}
return self;
}
/**
* 是否从xib初始化此类.
*
* @param isFromXib 是否从xib或sb初始化此类.
*
* 注意: 无论此类是否从xib或sb初始化,组件内部都将从xib文件初始化.
*
* @return 实例对象.
*/
- (instancetype) mcSetup: (BOOL) isFromXib
{
UIView * contentView = [[[NSBundle mainBundle] loadNibNamed: NSStringFromClass([self class]) owner:self options:nil] firstObject];
self.contentView = contentView;
contentView.translatesAutoresizingMaskIntoConstraints = NO;
// 这一句,是区别初始化方式后的,核心不同.
self.translatesAutoresizingMaskIntoConstraints = ! isFromXib;
[self addSubview: contentView];
self.backgroundColor = contentView.backgroundColor;
if (nil == self.backgroundColor) {
self.backgroundColor = [UIColor clearColor];
}
[self addConstraint: [NSLayoutConstraint constraintWithItem: contentView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem: self attribute:NSLayoutAttributeLeft multiplier: 1.0 constant: 0]];
[self addConstraint: [NSLayoutConstraint constraintWithItem: contentView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem: self attribute:NSLayoutAttributeRight multiplier: 1.0 constant: 0]];
[self addConstraint: [NSLayoutConstraint constraintWithItem: contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem: self attribute:NSLayoutAttributeTop multiplier: 1.0 constant: 0]];
[self addConstraint: [NSLayoutConstraint constraintWithItem: contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem: self attribute:NSLayoutAttributeBottom multiplier: 1.0 constant: 0]];
[self setup];
return self;
}
- (void)setup
{
/* 子类需要继承此方法,以完成自定义初始化操作. */
}
- (void)reloadData
{
/* 子类根据需要,自行实现. */
}
- (UIViewController*)viewController {
for (UIView* next = [self superview]; next; next = next.superview) {
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController*)nextResponder;
}
}
return nil;
}
- (void)back
{
if (nil != self.viewController.navigationController) {
[self.viewController.navigationController popViewControllerAnimated: YES];
}
else{
[self.viewController dismissViewControllerAnimated: YES completion:NULL];
}
}
- (NSLayoutConstraint *)heightContronstraint
{
__block NSLayoutConstraint * heightCons = nil;
[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint * obj, NSUInteger idx, BOOL *stop) {
if (NSLayoutAttributeHeight == obj.firstAttribute && nil == obj.secondItem && [obj.firstItem isEqual: self]) {
heightCons = obj;
* stop = YES;
}
}];
return heightCons;
}
+ (instancetype)sharedInstance
{
/* 子类应根据需要重写这个方法. */
return nil;
}
- (id)virtualModel
{
return nil;
}
- (void)setModel:(id)model
{
_model = model;
// 更新视图.
[self updateView];
}
- (id)model
{
id model = _model;
if(YES == self.isTest){
model = self.virtualModel;
}
return model;
}
- (void)updateView
{
/*子类应根据需要重写此方法.默认不做任何处理.*/
}
- (BOOL)isTest
{
/* 子类应根据自己需要,重写这个方法. */
return NO;
}
@end
你的Xib视图组件,应该由一个 MCComponent的子类的.h/.m与一个同名的 .xib 文件组成,如MCTextComponent.h, MCTextComponent.m, MCTextComponent.xib.此时应把XIB的File's Owder与自定义的MCComponent关联起来.按照以上步骤,即可实现图示效果.
此策略已经在我们的项目中试用了一段时间,也已经填了些坑,多次优化,感兴趣的可以直接拿过去用.但是,基于XIB的视图模块化,终究还是需要手动的参与,对工作效率的提升也似乎达到了一个极限:因为它终究需要人工深度参与.关于它的讨论,暂时到此为止.
目前的探索: 基于 masonry 的视图模块化
masonry,是一个基于纯代码的AutoLayout库.初次涉及时,只是感觉它很方便,既有Xib的易读性,又有纯代码的灵活性.试用一段时间之后,突然想到: 或许借助masonry,建立一个纯代码的不依赖Xib的AutoLayout视图组件机制.
目前能得到的效果
- 视图基于 AutoLayout;
- 视图自动适配不同屏幕尺寸;
- 视图完全独立于数据与业务逻辑;
- 视图严肃仅与父视图有位置关系;
- 可以将视图模块的元素与模块同名属性自动关联;
- 仅需知道父视图的宽高,模块内某一个UI元素的宽高, UI元素的 bottom 与 right, 就可以唯一确定任意元素的位置.
核心理论基础: AutoLayout中,如何唯一确定元素在不同尺寸屏幕上的位置?
- 既定方案,必须基于AutoLayout,至于AutoLayout与Frame的区别于优势,不做赘述.
- 在不考虑多屏幕兼容的情况下, AutoLayout,可以直接使用固定的约束常量值来确定,但是 马上iPhone 7 都要出来了,指不定什么尺寸呢? 一个机型,一个UI代码?是不是想想都让人头大!
- 考虑到多屏幕尺寸,UI设计图等比缩放的常用情况,我分享一个可以唯一确定UI元素的方案:
[subView makeConstraints:^(MASConstraintMaker *make) {
UIView * superView = subView.superview;
make.width.equalTo(superView).multipliedBy(subWidth / superWidth);
make.height.equalTo(superView).multipliedBy(subHeight / superHeight);
make.right.equalTo(superView).multipliedBy(subRight / superWidth);
make.bottom.equalTo(superView).multipliedBy(subBottom / superHeight);
}];
以上代码,是整个代码的核心,其巧妙之处在于:不使用constant,而是使用比例来指定约束.选取的是 width,height,right,bottom,而不是其他属性,其巧妙之处,大家试用下其他属性就知道了.
核心代码,打造自己的视图模块库.
直接继承YFViewComponent类,然后实现类方法 subViewsConfig 即可.
//
// YFViewComponent.h
// iOS122
//
// Created by 颜风 on 15/10/6.
// Copyright (c) 2015年 iOS122. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
* 预定义常量的声明.
*/
extern const NSString * YFViewComponentSelfHolderWidthKey; //!< 同一设计图中,视图模块本身的宽度.
extern const NSString * YFViewComponentSelfHolderHeightKey; //!< 同一设计图中,视图模块本身的高度.
extern const NSString * YFViewComponentSubViewsKey; //!< 同一设计图中,模块的所有子视图.
extern const NSString * YFViewComponentSubViewClassNameKey; //!< 子视图的类型.
extern const NSString * YFViewComponentSubViewPropNameKey; //!< 子视图对应的属性,模块中应有属性与其对应,且可通过此属性访问对应的子视图.
extern const NSString * YFViewComponentSubViewHolderWidthKey; //!< 同一设计图中,子视图的宽度.
extern const NSString * YFViewComponentSubViewHolderHeightKey; //!< 同一设计图中,子视图的高度.
extern const NSString * YFViewComponentSubViewHolderRightKey; //!< 同一设计图中,子视图的右内边距值(right).
extern const NSString * YFViewComponentSubViewHolderBottomKey; //!< 同一设计图中,子视图的底部边距值(bottom).
@interface YFViewComponent : UIView
/**
* 子视图配置信息.
*
* 子类应重写覆盖此方法.
*
一个示例:
@{
YFViewComponentSelfHolderWidthKey: @640.0,
YFViewComponentSelfHolderHeightKey: @155.0,
YFViewComponentSubViewsKey:
@[@{
YFViewComponentSubViewClassNameKey: NSStringFromClass([UIImageView class]) ,
YFViewComponentSubViewPropNameKey: @"imageView", YFViewComponentSubViewHolderWidthKey: @160, YFViewComponentSubViewHolderHeightKey: @120, YFViewComponentSubViewHolderBottomKey: @140, YFViewComponentSubViewHolderRightKey: @180
}]}
*
* @return 返回子视图的配置信息.
*/
+ (NSDictionary *) subViewsConfig;
@end
//
// YFViewComponent.m
// iOS122
//
// Created by 颜风 on 15/10/6.
// Copyright (c) 2015年 iOS122. All rights reserved.
//
#import "YFViewComponent.h"
/**
* 预定义常量的定义.
*/
const NSString * YFViewComponentSelfHolderWidthKey = @"YFViewComponentSelfHolderWidthKey";
const NSString * YFViewComponentSelfHolderHeightKey = @"YFViewComponentSelfHolderHeightKey";
const NSString * YFViewComponentSubViewsKey = @"YFViewComponentSubViewsKey";
const NSString * YFViewComponentSubViewClassNameKey = @"YFViewComponentSubViewClassNameKey";
const NSString * YFViewComponentSubViewPropNameKey = @"YFViewComponentSubViewPropNameKey";
const NSString * YFViewComponentSubViewHolderWidthKey = @"YFViewComponentSubViewHolderWidthKey";
const NSString * YFViewComponentSubViewHolderHeightKey = @"YFViewComponentSubViewHolderHeightKey";
const NSString * YFViewComponentSubViewHolderRightKey = @"YFViewComponentSubViewHolderRightKey";
const NSString * YFViewComponentSubViewHolderBottomKey = @"YFViewComponentSubViewHolderBottomKey";
@implementation YFViewComponent
- (instancetype)init
{
self = [super init];
if (nil != self) {
UIView * holderView = self;
NSDictionary * config = [[self class] subViewsConfig];
CGFloat superHeight = [[config objectForKey: YFViewComponentSelfHolderHeightKey] floatValue];
CGFloat superWidth = [[config objectForKey: YFViewComponentSelfHolderWidthKey] floatValue];;
NSArray * locatArray = [config objectForKey: YFViewComponentSubViewsKey];
[locatArray enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL *stop) {
NSString * classString = [obj objectForKey: YFViewComponentSubViewClassNameKey];
Class viewClass = NSClassFromString(classString);
if (YES != [viewClass isSubclassOfClass:[UIView class]]) {
return;
}
UIView * subView = [[viewClass alloc] init];
[holderView addSubview: subView];
NSString * viewKey = [obj objectForKey: YFViewComponentSubViewPropNameKey];
[holderView setValue: subView forKey: viewKey];
CGFloat subWidth = [[obj objectForKey: YFViewComponentSubViewHolderWidthKey] floatValue];
CGFloat subHeight = [[obj objectForKey: YFViewComponentSubViewHolderHeightKey] floatValue];
CGFloat subBottom = [[obj objectForKey: YFViewComponentSubViewHolderBottomKey] floatValue];
CGFloat subRight = [[obj objectForKey: YFViewComponentSubViewHolderRightKey] floatValue];
[subView makeConstraints:^(MASConstraintMaker *make) {
UIView * superView = subView.superview;
make.width.equalTo(superView).multipliedBy(subWidth / superWidth);
make.height.equalTo(superView).multipliedBy(subHeight / superHeight);
make.right.equalTo(superView).multipliedBy(subRight / superWidth);
make.bottom.equalTo(superView).multipliedBy(subBottom / superHeight);
}];
}];
}
return self;
}
+ (NSDictionary *) subViewsConfig{
return nil;
}
@end
一个示例: 仿网易新闻的新闻单元格.
这个示例,取材自网易新闻.图示中已经标注了单元格的宽高,单元格内各个UI元素的width,height,bottom,right.此处UI设计师可根据屏幕尺寸出图,我们根据一份跟定的设计图,直接使用 MarkMan(一个非常好用的标准工具)丈量标记即可. 因为我们是基于比例来添加约束,不同屏幕下,会自动等比变换.
这是一个简单的示例,为了方便演示,临时加上了:
//
// YFAutoTransView.h
// iOS122
//
// Created by 颜风 on 15/10/6.
// Copyright (c) 2015年 iOS122. All rights reserved.
//
#import "YFViewComponent.h"
@interface YFAutoTransView : YFViewComponent
@property (weak, nonatomic) UIImageView * imageView;
@property (weak, nonatomic) UILabel * titleLabel;
@property (weak, nonatomic) UILabel * detailLabel;
@property (weak, nonatomic) UIButton * chatBtn;
@end
//
// YFAutoTransView.m
// iOS122
//
// Created by 颜风 on 15/10/6.
// Copyright (c) 2015年 iOS122. All rights reserved.
//
#import "YFAutoTransView.h"
@implementation YFAutoTransView
+ (NSDictionary *) subViewsConfig{
NSNumber * holderWidth = @640.0;
NSNumber * holderHeight = @155.0;
NSArray * subConfig = @[
@[NSStringFromClass([UIImageView class]), @"imageView", @160, @120, @140, @180],
@[NSStringFromClass([UILabel class]), @"titleLabel", @420, @31, @55, @615],
@[NSStringFromClass([UILabel class]), @"detailLabel", @410, @60, @136, @605],
@[NSStringFromClass([UIButton class]), @"chatBtn", @120, @28, @141, @628]];
NSMutableArray * subViewsConfig = [NSMutableArray arrayWithCapacity: 42];
[subConfig enumerateObjectsUsingBlock:^(NSArray * obj, NSUInteger idx, BOOL *stop) {
if (6 != obj.count) {
return;
}
NSDictionary * configDict =
@{
YFViewComponentSubViewClassNameKey: obj[0],
YFViewComponentSubViewPropNameKey: obj[1], YFViewComponentSubViewHolderWidthKey: obj[2],YFViewComponentSubViewHolderHeightKey: obj[3], YFViewComponentSubViewHolderBottomKey: obj[4], YFViewComponentSubViewHolderRightKey: obj[5]
};
[subViewsConfig addObject: configDict];
}];
NSDictionary * config = @{
YFViewComponentSelfHolderWidthKey: holderWidth,
YFViewComponentSelfHolderHeightKey: holderHeight,
YFViewComponentSubViewsKey: subViewsConfig};
return config;
}
@end
这是运行时,我们看到对应属性,确实与UI元素关联了起来.
这是与数据结合之后的效果图.只是个初稿,还需要进一步调试.也就是说,以后再写UI界面,你的注意力将可以集中在 数据与视图本身的交互处理上.
YFAutoTransView * autoTestView = [[YFAutoTransView alloc] init];
autoTestView.frame = CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 155.0/2);
autoTestView.imageView.image = [UIImage imageNamed:@"autoTrans.png"];
autoTestView.titleLabel.text = @"爱马仕版苹果表开售8688元起";
autoTestView.titleLabel.font = [UIFont systemFontOfSize:15];
[autoTestView.titleLabel adjustsFontSizeToFitWidth];
autoTestView.detailLabel.text = @"爱马仕版苹果表盘和表带并不会单独销售.";
autoTestView.detailLabel.numberOfLines = 0;
autoTestView.detailLabel.font = [UIFont systemFontOfSize:12];
[autoTestView.chatBtn setTitle:@"跟帖" forState: UIControlStateNormal];
autoTestView.chatBtn.backgroundColor = [UIColor redColor];
[self.view addSubview: autoTestView];
小结
我在此文着重分享了我目前正在研究的 基于masonry的视图模块化方案.在以后的工作和学习中,我会继续使用与完善,以期进一步提高写UI界面的效率.可能尚有不完备之处,欢迎大家共同提出讨论.
如何把设计图自动转换为iOS代码? 在线等,挺急的!的更多相关文章
- 惊不惊喜, 用深度学习 把设计图 自动生成HTML代码 !
如何用前端页面原型生成对应的代码一直是我们关注的问题,本文作者根据 pix2code 等论文构建了一个强大的前端代码生成模型,并详细解释了如何利用 LSTM 与 CNN 将设计原型编写为 HTML 和 ...
- 借Adobe XD之力,自动生成Flutter代码
概述 今天,我们来聊聊一个专门为"懒人程序员"准备的工具--Adobe XD.使用它可以快速将原型设计图转换为可执行的Flutter代码, 而由于Flutter自身跨平台的特性,因 ...
- jenkins自动打IOS包(转发)
投稿文章,作者:一缕殇流化隐半边冰霜(@halfrost) 前言 众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段.用户们都是很挑剔的.如果一个公司的推广团队好不容易砸了重金推广了 ...
- 如何把iOS代码编译为Android应用
新闻 <iPhone 6/6 Plus中国销量曝光:单月销量650万>:据iSuppli Corp.中国研究总监王阳爆料,iPhone 6和iPhone 6 Plus在国内受欢迎的情况大大 ...
- 马赛克算法及iOS代码实现
之前做了一下相关涂鸦的东西,发现图片处理挺好玩的,就先讲讲马赛克的实现吧. 放大马赛克图片可以看到,可以看到一个个单色的小正方形.所以马赛克其实也就是把某一点的色值填充了它一定范围内的一个正方形,这样 ...
- SharpDevelop浅析_4_TextEditor_自动完成、代码折叠……
SharpDevelop浅析_4_TextEditor_自动完成.代码折叠…… SharpDevelop浅析_4_TextEditor_自动完成.代码折叠…… Parser及其应用: Code Com ...
- 一篇文章看懂iOS代码块Block
block.png iOS代码块Block 概述 代码块Block是苹果在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,Block是一种特殊的数据类型,其可以正常定义变量.作为参数.作为返 ...
- 将Winform和wpf的界面转换为CPF代码用来实现跨平台
CPF的设计器里带界面代码转换功能,将运行中的Winform或者wpf的程序界面转换为cpf代码,主要转换控件类型和布局,默认支持的是常用的原生控件.不支持Netcore,只支持.Netframewo ...
- php识别中文编码并自动转换为UTF-8
原文地址:http://www.codefans.net/articles/1272.shtml php自动识别编码,若里面有中文的话,将其转换为UTF-8就最好了,因为中文在Gbk编辑情况情况下,有 ...
随机推荐
- [Silverlight][linq to sql]不能找到linq to sql自动生成类型
最近在做Silverlight项目,结合使用了WCF RIA service,通过linq to sql自动生成model类型,使用起来非常方便.具体可见linq to sql之silverlight ...
- JavaScript高级程序设计--对象创建的三种方法
创建对象的三种方法: 1.工厂模式 工厂模式是软件工程领域广为人知的设计模式,这种模式抽象了创建具体对象的过程.下面是使用工厂函数创建对象的的一个例子. 2.构造函数: 从上面的例子中,我们看到构造函 ...
- C语言实现通用链表初步(三)----单元测试
前两节,我们已经完成了链表的一些操作,快来测试一下吧. 这里使用的单元测试工具名字叫"check". START_TEST(my_slist_1) { struct student ...
- 揭秘企业级web负载均衡完美架构
相信很多朋友对企业级的负载均衡高可用实例非常感兴趣,此篇文章根据成熟的线上环境而写,旨在帮助大家迅速架构一个企业级的负载均衡高可用的web环境. 此系统架构仅映射内网VIP的80及443端口于外网的J ...
- 新建mavent项目报错
1.找到自己项目 项目名\.settings\org.eclipse.wst.common.project.facet.core.xml 将<installed facet="jst. ...
- Actor的一生
Actor应该怎么去形容它呢?它是一段代码扮演的角色.它拥有自己的状态机,能根据外界的消息进行适当的反应.他有记忆能力,可以记住来自外界的多个消息并依次进行反应.Actor就像一个小的生命体,有自己的 ...
- 显卡(GPU)的基础知识
显卡的性能指标有: 流处理器(SP)数量 核心频率 流处理器的架构 显存容量 显存频率 显存带宽 1. 流处理器的数量 把一个GPU当成是一个画画的工厂,其中流处理器的数量就是画师的数量,其数量自然是 ...
- Spring-cloud之Ribbon负载均衡的使用及负载均衡策略配置(与Eurka配合使用)
什么是Ribbon,ribbon有什么用,个人先总结一下(不正确请提出讨论):Ribbon是基于客户端的负载均衡器,为我们提供了多样的负载均衡的方案,比如轮询,最小的并发请求的server,随机ser ...
- jquery的on()方法总结
摘自菜鸟教程 废话不说 直接上demo 实例: 向<p>元素添加click事件处理程序: <html> <head> <script src="ht ...
- Dreams save us. Dreams lift us up and transform us into something better.
Dreams save us. Dreams lift us up and transform us into something better.梦想能够拯救我们.梦想能够激励我们并让我们成为更好的人 ...