【IOS开发笔记03-视图相关】简单计算器的实现
UIView
经过前几天的快速学习,我们初步了解的IOS开发的一些知识,中间因为拉的太急,忽略了很多基础知识点,这些知识点单独拿出来学习太过枯燥,我们在今后的项目中再逐步补齐,今天我们来学习APP视图相关知识。
视图即UIView对象,我们上次用的按钮UIButton、UILabel或者UITableView皆是其子类;视图知道如何绘制自己与前端一致有一个层次的概念。
任何一个应用都会有一个UIWindow对象,与浏览器对象一致,他作为容器角色而存在,负责装载所有的视图控件,每个加入的视图便是一个子视图:subview,视图嵌套便形成了我们看到的APP界面,这点类似与html的dom结构。
视图的绘制分为两步:
① 层次结构上的每个视图(包括根视图UIWindow)分别绘制自身,视图将自己绘制到图层(layer)上,每个UIView都拥有一个layer属性,指向一个CALayer对象
② 所有视图的图像最终组成为一幅图像,绘制到屏幕上
为了更好的了解UIView的相关知识,我们这里做一个简单的计算器来说明其知识点吧。
其实说明这个知识点我可以选择很多项目之所以会选择计算器是因为内部会碰到数字与字符串转换,四则运算问题,也会遇到控件绑定事件等行为,帮助我们巩固基础吧。
这里新建一个单页应用:Calculator-app,自从昨天我知道了拖控件居然需要以拖动的方式建立关联后,我便决定不再使用拖的方式,我们这里使用代码生成界面,所以今天的目的是:
① 了解OC的数据类型转换
② 了解UIView的知识
③ 了解如何代码构建视图并且绑定事件
至于计算器的逻辑,不必太过在意
画圆
首先,我们在我们的UIView中画一个同心圆来了解UIView的相关知识,因为OC并没有提供绘制同心圆的视图对象,该知识点可以帮助我们更好的了解UIView。
新建一个UIView的子类:MyUICircle
每个UIView的子类有两个方法需要我们关注,第一个为初始化方法:
MyUICircle *circle = [MyUICircle alloc] initWithFrame:<#(CGRect)#>
其中initWithFrame是继承下来的初始化方法,带有一个CGRect类型的参数,该参数会赋予UIView的frame属性:
@property (nonatomic) CGRect frame;
CGRect包含另外两个结构,origin=>x, y; size=>width, height。四个都是float的基本结构,我们在全局控制器中试试其作用:
#import "ViewController.h"
#import "MyUICircle.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; //因为CGRect不是OC对象,所以不能接收OC的消息,也没有必要接收消息,一般这样建立一个OCRect对象
//注意,这里不是指针
CGRect frame = CGRectMake(, , , ); //创建基本视图对象
//这里已经确定好了坐标与尺寸
MyUICircle *circle = [[MyUICircle alloc] initWithFrame:frame]; //给一个背景,这里使用了颜色类的静态方法
circle.backgroundColor = [UIColor redColor]; //将视图加入主视图中
[self.view addSubview:circle]; } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
因为MyUICircle是一个空类,什么都没有做便没有贴代码了,这个是视图对应的主控制器,其与视图如何建立关联我们暂不关注,他提供一个方法viewDidLoad处理视图准备好的初始化动作,我们便将创建好的视图加入了其中,大家请看这块红斑:
这个时候的层次结构是
UIWIndow包含多个UIView,这里主UIView还包含一个MyUICircle对象,每个UIView可以根据superview属性找到自己的父对象
drawRect
drawRect为从UIView继承下来的第二个需要关注的方法,他负责在页面上绘图,我们可以重写drawRect达到自定义绘图的功能。
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
UIView的子类具有两个相似的属性,bounds与frame,我们都知道frame是用于视图本身布局用的,而bounds定义了一个矩形范围,表示视图的绘制区域。
视图在绘制时,会参考一个坐标系,bounds表示矩形位于自己的坐标系,而frame表示矩形位于父视图的坐标系,两个矩形大小是相等的。
-(CGRect)frame{
return CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height);
}
-(CGRect)bounds{
return CGRectMake(,,self.frame.size.width,self.frame.size.height);
}
bounds是相对于左上角位置的,不太好理解就写demo,我这里新建了一个子View帮助理解
- (void)viewDidLoad {
[super viewDidLoad]; //因为CGRect不是OC对象,所以不能接收OC的消息,也没有必要接收消息,一般这样建立一个OCRect对象
//注意,这里不是指针
CGRect frame = CGRectMake(, , , ); //创建基本视图对象
//这里已经确定好了坐标与尺寸
MyUICircle *circle = [[MyUICircle alloc] initWithFrame:frame]; //给一个背景,这里使用了颜色类的静态方法
circle.backgroundColor = [UIColor redColor]; //circle.bounds = CGRectMake(200, 200, 100, 100); UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
view2.backgroundColor = [UIColor yellowColor];
[circle addSubview: view2]; //将视图加入主视图中
[self.view addSubview:circle]; }
可以看到,子view是相对于父View布局的,这里与我们的absolute一致,如果改变父View的bounds呢:
- (void)viewDidLoad {
[super viewDidLoad]; //因为CGRect不是OC对象,所以不能接收OC的消息,也没有必要接收消息,一般这样建立一个OCRect对象
//注意,这里不是指针
CGRect frame = CGRectMake(, , , ); //创建基本视图对象
//这里已经确定好了坐标与尺寸
MyUICircle *circle = [[MyUICircle alloc] initWithFrame:frame]; //给一个背景,这里使用了颜色类的静态方法
circle.backgroundColor = [UIColor redColor]; //父类设置该参数造成的影响
circle.bounds = CGRectMake(, , , ); UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
view2.backgroundColor = [UIColor yellowColor];
[circle addSubview: view2]; //与view2参照物
UIView *view3 = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
view3.backgroundColor = [UIColor grayColor];
[self.view addSubview: view3]; //将视图加入主视图中
[self.view addSubview:circle]; }
可以看到,view2相对于父元素最初位置左移了10像素,所以修改了一个view的bounds边上修改了本地坐标的原点位置,最初的原点是0, 0。
那里view1修改了原点坐标让其右偏移了10像素,所以对应的子view便需要左偏,我理解下来是设置后将当前右上角的坐标变成了10像素,大概是这样吧。
这里为什么要强调这个bounds本地坐标呢,因为以后拖动相关的需求都会根据他做计算,这块有点绕,我们后续真实项目遇到再来纠结他吧,现在也说不清。
正式画圆
如果我们期待画一个铺满屏幕最大的圆,便需要通过bounds属性找到中心点:
- (void)drawRect:(CGRect)rect { CGRect bounds = self.bounds; //计算中心点
CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0; //根据宽高计算较小值的半径
float radius = (MIN(bounds.size.width, bounds.size.height) / 2.0); }
有了中心点与半径便可以画圆了,这里使用UIBezierPath类绘制圆形:
- (void)drawRect:(CGRect)rect { CGRect bounds = self.bounds; //计算中心点
CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0; //根据宽高计算较小值的半径
float radius = (MIN(bounds.size.width, bounds.size.height) / 2.0); UIBezierPath *path = [[UIBezierPath alloc] init]; //这里去看api吧,他们都说ios门槛高,原来什么都是英文啊
[path addArcWithCenter:center radius:radius startAngle:0.0 endAngle:M_PI * 2.0 clockwise:YES]; //开始绘制
[path stroke];
}
于是到此圆基本就出来了,至此我们对UIView有了一个基本的了解,接下来就让我们开始真实的计算器逻辑了吧
计算器
最简单的计算器拥有10个数字,+-*/,小数点,重置键,一个显示结果的文本框,并不复杂,我们这里便使用代码设计其UI。
首先,我们将数字画出来,根据前端的经验,数字按钮肯定是一个循环组成,dom上会留下一些标识,并且给父元素绑定事件即可,但是ios我们并不熟悉,所以先用最土的方法是画10个数字,在此之前,我们先简单研究下UIButton控件。
UIButton
这一小节参考了:http://justcoding.iteye.com/blog/1467999
UIButton是一个标准的UIController,所谓UI控件便是对UIView的的增强,也就是说UI控件一般继承至UIView,所以View的一些统一特性都被继承了下来了。
继承下来的属性
enabled,控件是否可用,与html控件一致,禁用后仍然可见,只是不可点击。
selected,当用户选中控件时,控件的selected属性便为YES。
contentVerticalAlignment,控件在垂直方向布置自身内容的方式,以下是可设置的值:
① UIControlContentVerticalAlignmentCenter
② UIControlContentVerticalAlignmentTop
③ UIControlContentVerticalAlignmentBottom
④ UIControlContentVerticalAlignmentFill
contentHorizontalAligment,为水平对齐的方式,可设置的值为:
① UIControlContentHorizontalAlignmentCenter
② UIControlContentHorizontalAlignmentTop
③ UIControlContentHorizontalAlignmentBottom
④ UIControlContentHorizontalAlignmentFill
事件通知
UIControll提供一个标准机制,来进行事件订阅和发布,当控件触发特定事件后,便会触发对应回调。
[myControl addTarget: myDelegate action:@selector(myActionmethod:) forControlEvents:UIControlEventValueChanged ];
可以使用addTarget绑定多个事件,这类事件一般来说都是标准的,比如js中的click事件,move等事件
UIControlEventTouchDown,点击事件,类似与js中的click
UIControlEventTouchDownRepeat,当点击数大于1时触发,类似doubleclick
UIControlEventTouchDraglnside,当触摸控件在窗口滚动时触发
UIControlEventTouchChanged,当控件的值发生变化时触发
UIControlEventEditingDidBegin,当开始编辑时触发,类似获取焦点吧
UIControlEventEditingChanged,当文本控件中的文本被改变时发送通知。
UIControlEventEditingDidEnd,当文本控件中编辑结束时发送通知。
......
与addTarget方法对应的是removeTarget,表达的是删除事件
使用allTargets获取一个控件的所有事件列表
之前是关于UIButton父类的事件,这里我们回到UIButton,首先说下两种初始化方法:
initWithFrame
UIButton *tmp;
CGRect frame; frame = CGRectMake(, , , );
tmp = [[UIButton alloc] initWithFrame:frame];
buttonWithType
这个是UIButton一个特有的类方法
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; typedef enum {
UIButtonTypeCustom = , // no button type 自定义,无风格
UIButtonTypeRoundedRect, // rounded rect, flat white button, like in address card 白色圆角矩形,类似偏好设置表格单元或者地址簿卡片
UIButtonTypeDetailDisclosure,//蓝色的披露按钮,可放在任何文字旁
UIButtonTypeInfoLight,//微件(widget)使用的小圆圈信息按钮,可以放在任何文字旁
UIButtonTypeInfoDark,//白色背景下使用的深色圆圈信息按钮
UIButtonTypeContactAdd,//蓝色加号(+)按钮,可以放在任何文字旁
} UIButtonType;
属性
这种方法创建是没有位置信息的,所以需要设置frame值:
CGRect btn2Frame = CGRectMake(10.0, 10.0, 60.0, 44.0);
btn2.frame =btn2Frame;
除此之外,我们需要设置按钮的文字,采用setTitle,带一个字符串和一个当前按钮的状态:
[btn1 setTitle:@"BTN1" forState:UIControlStateNormal];
我们也可以使用一个图片作为按钮:
[btn2 setImage:[UIImage imageNamed:@"pic"] forState:UIControlStateNormal];
最后可以为每种按钮设置标题的颜色和阴影,以及背景,
[btn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal];//设置标题颜色
[btn1 setTitleShadowColor:[UIColor grayColor] forState:UIControlStateNormal ];//阴影
[btn1 setBackgroundImage:[UIImage imageNamed:@"PIC"] forState:UIControlStateHighlighted];//背景图像
forstate决定了按钮将在何种状态下显示:
enum {
UIControlStateNormal = , //常态
UIControlStateHighlighted = << , // used when UIControl isHighlighted is set 高亮
UIControlStateDisabled = << , //禁用
UIControlStateSelected = << , // flag usable by app (see below) 选中
UIControlStateApplication = 0x00FF0000, // additional flags available for application use 当应用程序标志使用时
UIControlStateReserved = 0xFF000000 // flags reserved for internal framework use 为内部框架预留的
};
typedef NSUInteger UIControlState;
当按钮高亮或者禁用,UIButton可以调整自己的样式
添加事件(动作)
按钮还是需要绑定事件,他的事件绑定直接继承自UIView:
-(void)btnPressed:(id)sender{
UIButton* btn = (UIButton*)sender;
//开始写你自己的动作
}
[btn1 addTarget:self action:@selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];
这里我们再次回到计算器,我们首先生成数字的UI,然后为数字绑定事件,点击每个按钮在后台打印出数字:
- (void)onNumClick:(id)sender
{
self.msg.text = [sender currentTitle];
} - (void)viewDidLoad {
[super viewDidLoad]; //生成10个数字先,一行4个,一字排开
UIButton *tmp;
CGRect frame;
self.msg = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
[self.view addSubview:self.msg]; self.msg.text = @"数字"; for (int i = ; i < ; i++) {
frame = CGRectMake(, + * i, , );
tmp = [[UIButton alloc] initWithFrame:frame];
[tmp setTitle:[NSString stringWithFormat:@"%d", i] forState:UIControlStateNormal]; //不设置背景就是白色就看不到啦
tmp.backgroundColor = [UIColor grayColor]; //这里绑定事件,点击每个数字便重置msg
[tmp addTarget:self action:@selector(onNumClick:) forControlEvents:UIControlEventTouchDown]; [self.view addSubview:tmp];
}
}
如此一来,我们简陋的界面就出来了:
其中事件绑定的回调函数的sender参数,应该对应js函数中的e,在此我们知道了如何布局以及绑定事件,于是我们将界面稍微美化点,因为我这里用到了OC的字典,这里先插一段字典的知识吧。
NSDictionary
NSDictionary对应JS中的对象字面量,自从json对象出来后,这个对象非常重要,估计是逃不掉的啦。
NSDictionary代表不可变字典,意思是一旦初始化结束就不能增删元素了,这是其初始化的方法:
//创建多个字典
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
@"value1", @"key1",
@"value2", @"key2",
@"value3", @"key3",
@"value4", @"key4",
nil]; //根据现有的字典创建字典
NSDictionary *dic2 = [NSDictionary dictionaryWithDictionary:dic];
NSLog(@"dic2 :%@", dic2); //根据key获取value
NSLog(@"key3 value :%@", [dic objectForKey:@"key3"]); //获取字典数量
NSLog(@"dic count :%d", [dic count]); //所有的键集合
NSArray *keys = [dic allKeys];
NSLog(@"keys :%@", keys); //所有值集合
NSArray *values = [dic allValues];
NSLog(@"values :%@", values);
-- ::35.540 Calculator-app[:] dic2 :{
key1 = value1;
key2 = value2;
key3 = value3;
key4 = value4;
}
-- ::35.540 Calculator-app[:] key3 value :value3
-- ::35.540 Calculator-app[:] dic count :
-- ::35.541 Calculator-app[:] keys :(
key3,
key1,
key4,
key2
)
-- ::35.541 Calculator-app[:] values :(
value3,
value1,
value4,
value2
)
NSMutableDictionay
NSMutableDictionary是NSDictionary的子类,所以继承了NSDictionary的所有特性,并且可以使用方法动态添加:
[dictionary setObject:@"value" forKey:@"key"];
这里我们回到我们的计算器,因为我们知道到底有多少字符,所以这里直接使用不可变字典即可,但是最后转念一想好像数组也是可行的,所以就数组吧......
因为这里是学习ios开发,各位就不要在意小数点之类的细节了,至此基本UI便出来了,虽然很丑:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @property(retain,nonatomic) UILabel *msg; -(void) initLayout; @end #import "ViewController.h"
#import "MyUICircle.h" @interface ViewController () @end @implementation ViewController //计算机布局
//思考,感觉这里没有做到很好的分离
-(void) initLayout{
//生成10个数字先,一行4个,一字排开
UIButton *tmp;
CGRect frame;
self.msg = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
[self.view addSubview:self.msg];
self.msg.text = @"数字"; NSMutableArray *array = [[NSMutableArray alloc] init]; //插入5个数字,这里发生了装箱
for (int i = ; i < ; i++) {
NSString *n = [NSString stringWithFormat:@"%d", i];
[array addObject:n];
} [array addObject: @"+"];
[array addObject: @"-"];
[array addObject: @"*"];
[array addObject: @"/"];
[array addObject: @"="];
[array addObject: @"c"]; for(int i = ; i < ; i++) {
for(int j = ; j < ; j++){
if(i * + j > [array count] - ) break; frame = CGRectMake( + j * , + * i, , ); tmp = [[UIButton alloc] initWithFrame:frame];
[tmp setTitle: [array objectAtIndex:(i * + j)] forState:UIControlStateNormal]; //不设置背景就是白色就看不到啦
tmp.backgroundColor = [UIColor grayColor]; //这里绑定事件,点击每个数字便重置msg
[tmp addTarget:self action:@selector(onNumClick:) forControlEvents:UIControlEventTouchDown]; [self.view addSubview:tmp]; }
}
} - (void)onNumClick:(id)sender {
self.msg.text = [sender currentTitle];
} - (void)viewDidLoad {
[super viewDidLoad];
[self initLayout];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
这个时候我们来简单写一下其业务逻辑,逻辑肯定有问题,简单看功能就好:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @property(retain,nonatomic) UILabel *msg; //存取字符串显示的字符串
@property(retain,nonatomic) NSMutableString *resultStr; //存储最近一次有效的指令
@property(retain,nonatomic) NSMutableString *commondStr; @property(assign, nonatomic) int num1;
@property(assign,nonatomic) int num2; -(void) initLayout; -(void) calculatorNum; @end #import "ViewController.h"
#import "MyUICircle.h" @interface ViewController () @end @implementation ViewController //计算机布局
//思考,感觉这里没有做到很好的分离
-(void) initLayout{
//生成10个数字先,一行4个,一字排开
UIButton *tmp;
CGRect frame;
self.msg = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
[self.view addSubview:self.msg]; _resultStr = [[NSMutableString alloc]initWithString:@""];
_commondStr = [[NSMutableString alloc]initWithString:@""]; self.msg.text = _resultStr; NSMutableArray *array = [[NSMutableArray alloc] init]; //插入5个数字,这里发生了装箱
for (int i = ; i < ; i++) {
NSString *n = [NSString stringWithFormat:@"%d", i];
[array addObject:n];
} [array addObject: @"+"];
[array addObject: @"-"];
[array addObject: @"*"];
[array addObject: @"/"];
[array addObject: @"="];
[array addObject: @"c"]; for(int i = ; i < ; i++) {
for(int j = ; j < ; j++){
if(i * + j > [array count] - ) break; frame = CGRectMake( + j * , + * i, , ); tmp = [[UIButton alloc] initWithFrame:frame];
[tmp setTitle: [array objectAtIndex:(i * + j)] forState:UIControlStateNormal]; //不设置背景就是白色就看不到啦
tmp.backgroundColor = [UIColor grayColor]; //这里绑定事件,点击每个数字便重置msg
[tmp addTarget:self action:@selector(onNumClick:) forControlEvents:UIControlEventTouchDown]; [self.view addSubview:tmp]; }
}
} - (void)onNumClick:(id)sender { NSString *tmp = [sender currentTitle];
int flag = ; //此处监控输入,适合使用switch
if([tmp isEqualToString:@"c"]){
_resultStr = [[NSMutableString alloc]initWithString:@""];
//点击数字则重置
_commondStr = [[NSMutableString alloc]initWithString:@""]; } else if ([tmp isEqualToString:@"+"] || [tmp isEqualToString:@"-"] || [tmp isEqualToString:@"*"] || [tmp isEqualToString:@"/"]){
flag = ;
//如果之前已经有了命令,需要先显示计算结果,再给予新的命令
if([_commondStr isEqualToString:@""]) {
_commondStr = tmp;
} else {
_num2 = [_resultStr intValue];
[self calculatorNum ];
_num1 = ;
_num2 = ;
} } else if ([tmp isEqualToString:@"="]){
_num2 = [_resultStr intValue];
[self calculatorNum ];
_num1 = ;
_num2 = ;
} else {
//这个时候是输入数字的情况
if([_resultStr isEqualToString:@""]) {
_resultStr = [[NSMutableString alloc]initWithString:@""];
}
[_resultStr appendString:tmp];
} //第一次输入命令,便记录为第一个数字
if(flag == ) {
_num1 = [_resultStr intValue];
_resultStr = [[NSMutableString alloc]initWithString:@""];
} self.msg.text = _resultStr; } - (void)calculatorNum {
int r;
if ([_commondStr isEqualToString:@"+"]){
r = _num1 + _num2;
} else if([_commondStr isEqualToString:@"-"]) {
r = _num1 - _num2;
} else if([_commondStr isEqualToString:@"*"]) {
r = _num1 * _num2;
} else if([_commondStr isEqualToString:@"/"]) {
//不要在意那些逻辑了
r = _num1 / _num2;
} _commondStr = [[NSMutableString alloc]initWithString:@""];
_resultStr = [NSString stringWithFormat:@"%d", r]; } - (void)viewDidLoad {
[super viewDidLoad];
[self initLayout];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
【IOS开发笔记03-视图相关】简单计算器的实现的更多相关文章
- iOS开发笔记--UILabel的相关属性设置
在iOS编程中UILabel是一个常用的控件,下面分享一下UILabel的相关属性设置的方法. 很多学习iOS6编程都是从storyboard开始,用到UILabel时是将控件拖到storyboard ...
- iOS开发笔记7:Text、UI交互细节、两个动画效果等
Text主要总结UILabel.UITextField.UITextView.UIMenuController以及UIWebView/WKWebView相关的一些问题. UI细节主要总结界面交互开发中 ...
- IOS开发之表视图(UITableView)
IOS开发之表视图(UITableView)的基本介绍(一) (一):UITableView的基本概念 1.在IOS开发中,表视图的应用十分广泛和普及.因此掌握表视图的用法显得非常重要.一般情况下对于 ...
- iOS开发UI篇—xib的简单使用
iOS开发UI篇—xib的简单使用 一.简单介绍 xib和storyboard的比较,一个轻量级一个重量级. 共同点: 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: ...
- 【Swift】iOS开发笔记(二)
前言 这个系列主要是一些开发中遇到的坑记录分享,有助于初学者跨过这些坑,攒够 7 条发一篇. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案
标题:从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun ...
- iOS开发笔记-两种单例模式的写法
iOS开发笔记-两种单例模式的写法 单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...
- iOS开发笔记--什么时候调用layoutSubviews
iOS开发笔记--什么时候调用layoutSubviews 分类: iOS2014-04-22 16:15 610人阅读 评论(0) 收藏 举报 今天在写程序时候遇见layoutSubviews触发时 ...
- IOS开发笔记(4)数据离线缓存与读取
IOS开发笔记(4)数据离线缓存与读取 分类: IOS学习2012-12-06 16:30 7082人阅读 评论(0) 收藏 举报 iosiOSIOS 方法一:一般将服务器第一次返回的数据保存在沙盒里 ...
随机推荐
- 敏捷测试模式之Scrum及其实践
一. 敏捷开发模式简介 敏捷是近年来软件研发领域很火的一个词,采用敏捷开发模式的研发团队是越来越多了,尤其是敏捷模式中的Scrum更是佼佼者大行其道,这表明敏捷模式确有其好处,能给企业带来效率的 ...
- CentOS:Yum源的配置
# cd /etc/yum.repos.d/ # mv CentOS-Base.repo CentOS-Base.repo.bak # wget http://mirrors.163.com/.hel ...
- spring mvc 数据校验
1.需要导入的jar包: slf4j-api-1.7.21.jar validation-api-1.0.0.GA.jar hibernate-validator-4.0.1.GA.jar 2.访问页 ...
- 执行git push出现"Everything up-to-date"
在github上git clone一个项目,在里面创建一个目录,然后git push的时候,出现报错"Everything up-to-date" 原因:1)没有git add . ...
- Redis集群案例与场景分析
1.背景 Redis的出现确实大大地提高系统大并发能力支撑的可能性,转眼间Redis的最新版本已经是3.X版本了,但我们的系统依然继续跑着2.8,并很好地支撑着我们当前每天5亿访问量的应用系统.想当年 ...
- 用IntelliJ IDEA创建Gradle项目简单入门
Gradle和Maven一样,是Java用得最多的构建工具之一,在Maven之前,解决jar包引用的问题真是令人抓狂,有了Maven后日子就好过起来了,而现在又有了Gradle,Maven有的功能它都 ...
- 写自己的Socket框架(三)
在通信写完了以后,应用层接收到Socket抛上来的byte[],这个时候对于实际的写逻辑的开发者来说,这样的数据并不友好,我们就需要在应用层统一一个包的规则(应用层协议),处理完以后,然后再传给实际的 ...
- ABP(现代ASP.NET样板开发框架)系列之16、ABP应用层——数据传输对象(DTOs)
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之16.ABP应用层——数据传输对象(DTOs) ABP是“ASP.NET Boilerplate Project ...
- 【Win 10 应用开发】三维变换
所谓三维变换,其实是在二维平面上产生三维的视觉效果.前面老周简单提了一下透视效果,如果透视效果不能满需求,那可以考虑用三维变换. UIElement类有一个属性叫Transform3D,它定义的类型为 ...
- OpenCASCADE Interpolations and Approximations
OpenCASCADE Interpolations and Approximations eryar@163.com Abstract. In modeling, it is often requi ...