webView.dataDetectorTypes = UIDataDetectorTypePhoneNumber;//自动检测网页上的电话号码,单击可以拨打
接下来我们来简单讲一下,使用UIDataDetectorTypes自动检测电话、网址和邮箱。我们先来看看UIDataDetectorTypes有哪些枚举值。
typedef NS_OPTIONS(NSUInteger, UIDataDetectorTypes) {
UIDataDetectorTypePhoneNumber = 1 << 0, // Phone number detection
UIDataDetectorTypeLink = 1 << 1, // URL detection
#if __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
UIDataDetectorTypeAddress = 1 << 2, // Street address detection
UIDataDetectorTypeCalendarEvent = 1 << 3, // Event detection
#endif
UIDataDetectorTypeNone = 0, // No detection at all
UIDataDetectorTypeAll = NSUIntegerMax // All types
};
NS_OPTIONS一般用来定义位移相关操作的枚举值。UIDataDetectorTypeAddress,UIDataDetectorTypeCalendarEvent不在我们考虑的范围了。
UIWebView有dataDetectorTypes属性,UITextView也有dataDetectorTypes属性。我们来UITextView来举例。
UITextView *textView = [[UITextView alloc] initWithFrame:self.view.bounds];
textView.font = [UIFont systemFontOfSize:20];
textView.editable = NO;
textView.text = @"\r\n我的手机号不是: 13888888888 \r\n\r\n"
"我的博客刚刚在线网址: www.xxxxxx.com \r\n\r\n"
"我的邮箱: worldligang@163.com \r\n\r\n";
[self.view addSubview:textView];
运行起来看一下:
可以看出来就是一个简单的文本,电话号码,网址和邮箱都没有检测出来。下面我们来看看dataDetectorTypes作用。
textView.dataDetectorTypes = UIDataDetectorTypePhoneNumber;
设置textView.dataDetectorTypes的属性,即可检测文本中的电话。效果如下所示:
textView.dataDetectorTypes = UIDataDetectorTypeLink;
UIDataDetectorTypeLink检测网址和邮箱的。点击网址会跳转到相应的网页,点击邮箱可以调用系统的发邮件。
textView.dataDetectorTypes = UIDataDetectorTypeAll;
UIDataDetectorTypeAll可以检测检测电话、网址和邮箱。效果如下:
专门写了一个iOSStrongDemo以后都在这个iOSStrongDemo里面更新内容。下载地址:iOSStrongDemo
JUL 8TH, 2015 11:52 PM
今天加入一个QQ群,也算是一个圈子,群主的要求是满足他的三个条件。经过与群主的沟通,终于得到通过,顺利加入。
群主是一个93年的小伙,而且是河南的老乡。没想到小伙子这么有号召力。我也是偶然在我的空间发现他的,看他每天发的文章,还挺有意思。
90后的小伙子都这么厉害了,有什么理由不努力奋斗呢!多加入以下圈子,认识一下身边的牛人。说不定会有意外的收获。
今天我们来详细UIWebView用法。UIWebView是iOS内置的浏览器控件,可以浏览网页、打开文档等 能够加载html/htm、pdf、docx、txt等格式的文件.
用UIWebView我们就可以做一个简易的浏览器。效果如下:
首先创建UIWebView,这个不难,设置frame,然后添加到self.view上即可:
UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
webView.scalesPageToFit = YES;//自动对页面进行缩放以适应屏幕
[self.view addSubview:webView];
用UIWebView来加载网络地址,那我的博客:http://www.superqq.com 来举例。代码如下:
NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.superqq.com"]];
[self.view addSubview:webView];
[webView loadRequest:request];
NSString *path = [[NSBundle mainBundle] pathForResource:@"swift" ofType:@"html"];
NSURL* url = [NSURL fileURLWithPath:path];//创建URL
NSURLRequest* request = [NSURLRequest requestWithURL:url];//创建NSURLRequest
[webView loadRequest:request];//加载
UIWebView 还支持将一个NSString对象作为源来加载。你可以为其提供一个基础URL,来指导UIWebView对象如何跟随链接和加载远程资源:
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:path]];
设置这个属性,如果在加载的网页中遇到电话号码,直接单击就可以拨打,非常方便:
webView.dataDetectorTypes = UIDataDetectorTypePhoneNumber;//自动检测网页上的电话号码,单击可以拨打
UIWebView有五个代理方法,我们可以在不同的代理方法中,完成不同的需求。
//设置代理
webView.delegate = self;
//代理方法
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//返回YES,进行加载。通过UIWebViewNavigationType可以得到请求发起的原因
return YES;
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
//开始加载,可以加上风火轮(也叫菊花)
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//完成加载
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
//加载出错
}
创建四个按钮,分别是加载按钮、停止按钮、返回按钮、前进按钮:
NSArray *array = [NSArray arrayWithObjects:@"加载",@"停止",@"返回",@"前进", nil];
int far = (SCREEN.width - 200)/5;
for (int i = 0; i < array.count; i++) {
UIButton *button = [[UIButton alloc] init];
button.frame = CGRectMake( (i + 1) * far + 50 * i, SCREEN.height - 60, 50, 40);
button.tag = 200 + i;
[button addTarget:self action:@selector(actionClick:) forControlEvents:UIControlEventTouchUpInside];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor orangeColor]];
[button setTitle:array[i] forState:UIControlStateNormal];
[self.view addSubview:button];
}
给四个按钮绑定事件,根据tag值来区分每一个点击事件:
- (void)actionClick:(UIButton *)button
{
switch (button.tag) {
case 200:
{
[self.webView reload];//加载
}
break;
case 201:
{
[self.webView stopLoading];//停止加载
}
break;
case 202:
{
[self.webView goBack];//返回
}
break;
case 203:
{
[self.webView goForward];//前进
}
break;
default:
break;
}
}
大功告成,再来看看效果:
以上分享的内容我做了一个demo,需要的话可以点击这里下载:UIWebView用法详解
JUL 7TH, 2015 10:33 PM
股票还在努力的往下跌,怎么办呢?我这真是杞人忧天啊。谁说我不着急呢?我的模拟炒股都亏的过半了吧。你想想那些真真炒股的人该有多担心。
罢了罢了,我还是滚去撸代码,消灭bug吧。
随着iPhone的日趋强盛,随着AppStore的不断壮大,海量的应用如潮水般涌来。据统计AppStore上的应用早已过120万,Google Play Store更是超于AppStore,达到150万。
知道120万、150万是什么概念吗?人生不过短短两三万天。也就是说,如果你一天用一个APP的话,AppStore够你用40辈子,Google Play Store够你用50辈子,前提是,你必须生下来就开始玩手机。
这么多应用,不知道有没有你的贡献。估计正在看文章的你也贡献了好几个了吧。AppStore里面也有我的贡献。??
开发一个APP不是那么容易的一件事,有很多坑等着你去踩。今天我们就抛出一个格式化时间的坑。
之前的文章,讲到过:NSDate和NSString相互转换。里面提到过如何讲NSDate转化成NSString。代码如下:
//获取系统当前时间
NSDate *currentDate = [NSDate date];
//用于格式化NSDate对象
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//设置格式:zzz表示时区
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"];
//NSDate转NSString
NSString *currentDateString = [dateFormatter stringFromDate:currentDate];
//输出currentDateString
NSLog(@"%@",currentDateString);
运行起来,看看打印的内容:
2015-07-07 22:08:57.422 TestDemo[6756:1555205] 2015-07-07 22:08:57
这样写是不是没有什么问题。看着应该是没什么问题,其实问题很大。但是如果你改一下系统设置:语言设置成印度尼西亚文,时间设置成12小时制。
大家应该知道如何去设置吧,不会设置的请不要告诉我你是一名iOS开发工程师。再次编译起来,看看打印内容如下:
2015-07-07 22:09:14.928 TestDemo[6762:1555466] 2015-07-07 10.09.14 PM
是不是愣住了,怎么会这么奇葩,时间怎么是.呢?还有更奇葩的呢,你去设置设置其他语言试试,也许有更多的收获。
这也是我们这两天遇到的问题,跟用户几经沟通之后,终于抓到log,发现问题竟然是格式化导致的。怎么解决呢?
这个时候NSLocale的重要性就体现出来了。NSLocale作为大家都不常用的一个类,NSLocale类是将与国家和语言相关的信息进行简单的组合,包括货币、语言、国家等的信息。
所以很简单,我们把dateFormatter的locale属性改一下即可解决这个问题。将下面代码放在dateFormatter初始化之后:
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
dateFormatter.locale = usLocale;
看看问题解决没有,编译一下:
2015-07-07 22:20:08.411 TestDemo[6769:1556968] 2015-07-07 22:20:08
果然,问题得到完美解决了。
既然谈到NSLocale,我们就来简单了解一下:
+ ISOCountryCodes// 所有的ISO定义的国家地区编码
+ ISOCurrencyCodes// 所有的ISO定义的货币编码
+ ISOLanguageCodes// 所有ISO定义的语言编码
以上我们可以用NSLog打印出来看一看。
FOUNDATION_EXPORT NSString * const NSCurrentLocaleDidChangeNotification NS_AVAILABLE(10_5, 2_0);
[[NSLocale currentLocale] localeIdentifier];
还有很多关于NSLocale的用法,自己动手多尝试。还有一个小问题。
看了这么久的NSLocale了,你知道NSLocale怎么读吗?不要翻译噢,看看你读的到底对不对?
JUL 6TH, 2015 11:40 PM
又是一年的暑假日期而至,小孩子放假,都会到在外打工的父母身边。孩子想父母,父母也思念着自己的孩子。我身边的亲戚朋友的孩子 也都来了。这个暑假又该热闹起来。
我有一个表妹,今年参加完高考,对自己的成绩不是特别满意。上次我回老家,刚好她给我一起来上海。准备来上海锻炼一下。
车上我问她,准备去哪上学?她说不想上了,想打工。我没有怎么劝她,我想让她体验一下打工的生活,她就知道还是上学好。
一个高中生,出来找工作,困难可想而知。经姐姐介绍,进了一家餐厅工作。工资也不是很高。干了两天,我问她怎么样?她说,高二要是来让我体验一下,我一定能考上一本。
也许真的如她所说的那样,但是谁知道呢?时间也不会倒流,她也不再可能再参加一次高考了。人只有吃过苦头,才知道努力。这是件好事,大学好好把握也是一样的。
无论处于什么困境,只要知道努力,我觉得什么时候都不晚。关注iOS开发微信公众号:iOSDevTip
每天都随便扯扯,回到正题。今天我们做一个时间选取器,很简单,效果如下:
我们自定义一个LGDatePickerView,在LGDatePickerView里面实现。
背景是半透明的,点击的灰色背景的时候,时间选取器消失。在LGDatePickerView初始化方法里,代码如下:
- (id)init
{
self = [super init];
if (self) {
//背景半透明,绑定取消方法
UIControl *control = [[UIControl alloc] initWithFrame:SCREEN_BOUNDS];
control.backgroundColor = [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.5f];
[self addSubview:control];
[control addTarget:self action:@selector(actionCancel:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
绑定的actionCancel方法:
- (void)actionCancel:(id)sender
{
[self removeFromSuperview];
}
看到上面的确定取消按钮,你会怎么做,写一个UIView上面放两个UIButton。这样做也是可以实现的。我们还可以用UIToolbar。在LGDatePickerView初始化方法里加上下面这段代码:
// Toolbar
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, SCREEN.height - 250, SCREEN.width, 50)];
toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
UIBarButtonItem *itemCancelDone = [[UIBarButtonItem alloc] initWithTitle:@"确定" style:UIBarButtonItemStylePlain target:self action:@selector(actionConfirm:)];
UIBarButtonItem *itemCancel = [[UIBarButtonItem alloc] initWithTitle:@"取消" style:UIBarButtonItemStylePlain target:self action:@selector(actionCancel:)];
UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[toolbar setItems:[NSArray arrayWithObjects:itemCancel,space,itemCancelDone, nil]];
[control addSubview:toolbar];
actionCancel上面已经实现了。下面实现actionConfirm方法。它有什么作用呢?
时间选取器消失
- (void)actionConfirm:(id)sender
{
if ([self.delegate respondsToSelector:@selector(datePickerView:didSelectTime:)]) {
[self.delegate datePickerView:self didSelectTime:self.datePicker.date];
}
[self removeFromSuperview];
}
在LGDatePickerView.h
@protocol LGDatePickerViewDelegate <NSObject>
- (void)datePickerView:(LGDatePickerView *)datepicker didSelectTime:(NSDate *)time;
@end
在LGDatePickerView.h定义一个全局变量:
@property (nonatomic, strong) UIDatePicker *datePicker;
在LGDatePickerView初始化方法里加上下面这段代码:
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.backgroundColor = [UIColor whiteColor];
datePicker.datePickerMode = UIDatePickerModeCountDownTimer;
datePicker.date = [NSDate date];
datePicker.frame = CGRectMake(0, SCREEN.height - 200, SCREEN.width, 220);
[control addSubview:datePicker];
self.datePicker = datePicker;
使用起来很简单,创建一下,然后加载self.view上面即可:
LGDatePickerView *datePicker = [[LGDatePickerView alloc] init];
datePicker.delegate = self;
datePicker.datePicker.date = [NSDate date];
datePicker.frame = self.view.bounds;
[self.view addSubview:datePicker];
以上就实现了iOS开发自定义时间选取器,代码不难,有什么问题,欢迎提问哈。
JUL 5TH, 2015 11:35 PM
最近这一段时间,你身边是不是大多数人都在谈论股票?那就对了,无论走到哪都能听到,今天又绿了,我的股票跌停了,冲上5000点啦,等等之类的话。
我还不是一个股民,一直都不是。因为不懂,不敢入市;因为有人跳楼,害怕入市;最主要的原因是,因为手里没有人民币。
人们常说:股市有风险,入市需谨慎。但是还是很多人挤破头皮,往里进。站着进去,趴着出来;笑着进去,哭着出来。
作为一名屌丝,谁不想逆袭呢,谁不想通过炒股赚钱呢?
最近群里,有个前同事做后台的。他进了一家证劵公司,做后台。应该是年初进去上班的,刚好赶上一波牛市。他买了几只股,好像都不错。
其中有一只股,买的时候是30左右。在60几出的。赚了几万块钱吧。想想真的很不错,啥都不干白赚几万块钱,谁看了不心动呢。说实话,我也心动。
估计是受到他的影响,公司里有些同事也开始炒股了。当然,有的人可能早就在炒股,只是之前股市不景气,大家都不谈论罢了。
看着别人赚钱容易,到自己了估计就难了。真的是这样,尤其是股市里面的钱,真的不是那么好赚的。通过炒股走上逆袭之路,那更是难上加难。
大家都在谈论股票,我也不能闲着啊。就Appstore里面找了一个模拟炒股软件,试着玩玩看。说不定能赚。
里面有100万,是用来模拟炒股的。反正,是假的,就随便挑了几只股票入手。一共投了30多万吧。还别说,当天就赚了一万多。突然发现自己有成为股神的潜质,哈哈。
紧接着,第二天,第三天,每天都能赚个两三万,第五天的时候,模拟资金已高达110多万。这要是真钱,该多好啊。那我岂不是白白赚了10万块钱。所以你想想,那些有钱的人,真的是越来越有钱。随便弄一下,几百万就来了。
与此同时,其他炒股的同事都在赚,投一万多,赚一千多。看起来还真不错。看到大家都赚钱了,我这个股票小白,模拟都能赚10万块。是不是很想入市啊。
事情并没有想象的那么简单。随后的两三周,股票大跌,各种跌停。有的股票都快跌一半了。包括我前同事买的那个股票从60多又跌回到30多了。不过幸好,他已经抛了。
并不是每个人都那么幸运。有的人都快损失过半了。这种过山车的股市,真让人受不了。炒股不仅有风险,还严重影响生活。与其这样,还不如好好思考如何提高自己的技术。
再看看我的模拟炒股战绩:
经过前面的大跌,股市下一步走向如何呢?或许会继续跌一些,但是我更愿意相信股市会涨,我也希望能涨,让更多被套牢的朋友赚点。我不是股神,无法给出精准的答案。
也许在中国根本就不存在巴菲特口中的价值投资理论。有的只是政策市。
股市大跌之后,我也不再想通过股市走向逆袭之路。作为一名屌丝程序员,还是安心的做个美男子,去实现更多有价值的理想吧。
JUL 4TH, 2015 2:14 PM
昨天去公司加班的人请举手,不是只有我一个吧?(??)我觉得加班的人应该不少吧。今天周日,应该不需要去加班了。心里暗暗自喜,终于可以休息一天啦。(??)
说到加班,应该是程序猿心里的痛啊。不加班吧,东西做不完;加班吧,身体吃不消。作为程序猿真的不容易,每天从早忙到晚。突然有一天,六点下班,看见太阳还在等我,心里被踢有多高兴。
弱弱的问一下:加班好不好?
要看这个问题问谁了。如果问老板,老板肯定美滋滋的说,加班好啊,说明你有责任心,有上进心,把公司当成自己的…
如果问我,哈哈,我当然说加班不好啦,不然会被打死的。开个玩笑。说句实话,加班肯定是不好的,尤其是对程序猿来说。每天面对电脑,每天坐着,时间长了,各种问题就凸显出来。
但是,我说加班不好有用吗?如果我要是老板,我就直接让员工在家办公。(??)所以大家感觉支持我吧,说不定哪天我真的…
接着昨天的UIButton中的三个UIEdgeInsets属性,今天我们具体谈谈UIButton的contentEdgeInsets、titleEdgeInsets、imageEdgeInsets属性。
UIButton *button = [[UIButton alloc] init];
button.frame = CGRectMake(50, 200, 200, 50);
[button setTitle:@"我是UIButton" forState:UIControlStateNormal];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor orangeColor]];
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[self.view addSubview:button];
创建一个button,让button的title居左,以便观察:
@property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR; // default is UIEdgeInsetsZero
contentEdgeInsets里有一个content应该指的就是UIButton的title。
上一篇文章我们讲了UIEdgeInsets是个结构体类型。里面有四个参数,分别是:top, left, bottom, right。这四个参数表示距离上边界、左边界、下边界、右边界的距离。
这四个参数的值可以为正值,也可以为负值。拿left举例:
left = 10; //代表以当前位置为基准,向右移动10个像素
left = -10; //代表以当前位置为基准,向左移动10个像素
button.contentEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
向右移动20个像素,left = 20,就可以了。
button.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0);
titleEdgeInsets和contentEdgeInsets的作用差不多。我们及设置contentEdgeInsets,又设置titleEdgeInsets,会怎样呢?
button.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
button.contentEdgeInsets = UIEdgeInsetsMake(0, 20 , 0, 0);
看一下效果:
UIButton *button = [[UIButton alloc] init];
button.frame = CGRectMake(50, 200, 200, 200);
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor orangeColor]];
[button setImage:[UIImage imageNamed:@"test"] forState:UIControlStateNormal];
[self.view addSubview:button];
运行一下:
button.imageEdgeInsets = UIEdgeInsetsMake(0, 50, 0, 0);
看看效果:
button.imageEdgeInsets = UIEdgeInsetsMake(0, -50, 0, 0);
看看效果:
大家可以自行设置其他三个参数看看效果是怎样的,自己动手便于理解。
JUL 3RD, 2015 11:29 PM
随着时间的推移,随着我的坚持,公众号的订阅用户已经越来越多了。非常感谢大家的信任,我会再接再厉,努力为大家提供更多优秀的文章。
当初创建iOS开发( iOSDevTip ),只是自己的兴趣。刚开始还不怎么会用微信公众号的后台,连发图文消息都不会。不知道怎么去编辑,当初的微信公众号后台也没有现在这么强大。我还以为就是个一对多的聊天工具呢。(??)
慢慢的我学会了编辑文章,成为一个真正意义上的小编。每天负责为大家推送一些iOS相关的技术文章。每天到各大论坛、网站、大神的博客找一些好的文章。这个过程是漫长的,但是是值得的。
找文章的过程中,对自己来说,也是学习的好机会。如果没有这个公众号,我可能就看不到那么多的技术文章,也不能为大家推荐文章,自己也不会建立博客。
现在微信团队已经邀请我开通原创功能,以后,我就会多发一些原创内容。一个人的力量比较是有限的,订阅的用户如果有喜欢写技术文章的,欢迎头投稿给我,我的邮箱:worldligang@163.com
相信我,你的付出也会有回报的。
今天是周六,不知道正在看文章的你有没有在加班。没有加班的,就好好休息一下吧;加班的,我只能同情一下啦。今天我们来看看UIButton中的三个UIEdgeInsets属性。
UIEdgeInsets是什么?我们点进去看一下:
typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to ‘outset‘
} UIEdgeInsets;
UIEdgeInsets是个结构体类型。里面有四个参数,分别是:top, left, bottom, right。这四个参数表示距离上边界、左边界、下边界、右边界的距离。
不知道大家发现没有,UIButton里面有三个UIEdgeInsets属性,分别是:
@property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets titleEdgeInsets; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets imageEdgeInsets; // default is UIEdgeInsetsZero
contentEdgeInsets后面有个UI_APPEARANCE_SELECTOR是什么意思呢?
提示:UI_APPEARANCE_SELECTOR标记的属性都支持通过外观代理来定制。
举例,设置UIButton的contentEdgeInsets属性,可以直接调用:
[[UIButton appearance] setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
关于UIButton三个UIEdgeInsets属性的作用,下一篇文章介绍。
JUL 2ND, 2015 10:18 PM
题外话:时间依旧过的很快,不知不觉2015年就过去一半了。感觉自己好像没有大的改变,只能感叹时间飞逝,却不能有所收获。
我从来都不是一个安于现状的人,改变自己的想法从未停止过。我想大多数人都跟我有类似的想法。但是为什么很难有所成就呢?我觉得最重要的原因就是,只是想一下,而没有去行动。
这是一个全民创业的时代,不把握机会,只能错过。错过的机会,越多遗憾就越多。有句话说:老了之后,回想人生,不会因为自己做过什么而后悔,而会因为自己没有做过什么而遗憾。不想给人生留下遗憾,所以努力去尝试是唯一的选择。
随便感慨一下。每天上班太舒服了,淡忘了自己的理想,借此提醒一下自己。
来来,收回思路,今天我们来讲如何让UIButton文字居左显示?我们都应该写过让UILabel的text居左显示。代码也非常简单。
实现文字居左显示代码如下:
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(50, 100, 200, 50);
label.text = @"我是label";
label.textAlignment = NSTextAlignmentLeft;
label.backgroundColor = [UIColor orangeColor];
[self.view addSubview:label];
运行起来看一下效果:
label.backgroundColor = [UIColor orangeColor];设置label的背景颜色方便我们参考。你是不是这样做的。依次类推UIButton也很简单,你肯定能想到。我们来看看。
UIButton *button = [[UIButton alloc] init];
//设置坐标
button.frame = CGRectMake(100, 100, 100, 50);
//设置标题
[button setTitle:@"我是UIButton" forState:UIControlStateNormal];
//设置标题颜色
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
//设置背景颜色
[button setBackgroundColor:[UIColor orangeColor]];
[self.view addSubview:button];
以上代码是创建一个button,设置坐标、标题、和标题颜色。
按照UILabel文字居左的写法,UIButton应该这么写:
button.titleLabel.textAlignment = NSTextAlignmentLeft;
运行一下看一下效果:
我们发现UIButton的文字还是居中显示。竟然没有居左显示,怎么办呢?进UIButton看看,还有哪些属性。很快发现:
@property(nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment; // how to position content hozontally inside control. default is center
typedef NS_ENUM(NSInteger, UIControlContentHorizontalAlignment) {
UIControlContentHorizontalAlignmentCenter = 0,
UIControlContentHorizontalAlignmentLeft = 1,
UIControlContentHorizontalAlignmentRight = 2,
UIControlContentHorizontalAlignmentFill = 3,
};
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
再次运行起来看效果:
果然可以,是不是看着居左显示很难看,太靠边了。很简单,设置UIButton的titleEdgeInsets属性:
button.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
这样button的title就距左边10个像素的距离。
居右显示就很简单了:
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
ok,UIButton文字居左显示完成了。更多iOS技术请点击刚刚在线 : www.superqq.com
JUL 2ND, 2015 12:38 AM
子曰:学而不思则罔,思而不学则殆。
在上一篇文章中:EGOCache缓存框架详细讲解 提到EGOCache可以设定缓存过期时间,默认是1天。查看了一下EGOCache源码,设置默认时间:
[self setDefaultTimeoutInterval:86400];
//86400 = 24 * 60 * 60 刚好是一天时间。
EGOCache为什么要提供设定缓存过期时间呢?或者说设定缓存过期时间有什么好处呢?我觉得最大的好处就是可以定时清除缓存。可以设置某一项的缓存时间,很方便管理缓存。
那么问题来了:
带着这两个问题,我们来继续分析。
记得在公司里,老板经常会举这样的例子:
某某同志,刚来我们公司的时候,遇到问题就知道抱怨。从来不知道去思考怎么解决,只知道把问题抛给领导。工作半年下来,成长了很多。现在碰到问题,不仅把问题抛出来,而且还提供了自己的解决方案...
类似的例子,相信大家都听过。同样,既然前面我们提出这两个问题,我们也先来思考一下,如果我们来做该怎么解决?
如果让我来写的话,我脑海里初步实现方法有几个:
当然,还有一些方法,不一一例举了。仔细想想,这些方法弊端很容易显露出来。
这些方法都被排除了,还有好的方法吗?继续往下看:
仔细查看EGOCache源码,发现在initWithCacheDirectory:方法里,每次初始化EGOCache实例对象的时,会遍历一遍plist文件中所有已存在的缓存项,拿每个缓存项的时间和当前时间作比较,缓存项过期时间早于当前时间,则删除对应缓存文件,并删除 plist 文件中对应 key 的记录。
具体实现代码如下:
_cacheInfo = [[NSDictionary dictionaryWithContentsOfFile:cachePathForKey(_directory, @"EGOCache.plist")] mutableCopy];
if(!_cacheInfo) {
_cacheInfo = [[NSMutableDictionary alloc] init];
}
NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
NSMutableArray* removedKeys = [[NSMutableArray alloc] init];
for(NSString* key in _cacheInfo) {
//判断缓存项过期时间是否早于当前时间
if([_cacheInfo[key] timeIntervalSinceReferenceDate] <= now) {
//如果缓存项过期时间早于当前时间,移除缓存项
[[NSFileManager defaultManager] removeItemAtPath:cachePathForKey(_directory, key) error:NULL];
//把过期的缓存项对于的key保存到removedKeys里面
[removedKeys addObject:key];
}
}
[_cacheInfo removeObjectsForKeys:removedKeys];
看到这些,是不是觉得人家思路特牛叉,反正,我是觉得这个作者不简单。到这一步就解决了吗?
细心的童鞋会发现:EGOCache是个单列类,也就是说整个程序应用周期只初始化一次。
+ (instancetype)globalCache {
static id instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
每次初始化的时候去判断了缓存项是否过期,这样做非常正确。思考一个场景:
继续分析EGOCache源码发现,EGOCache在读取一个缓存项的时候,先判断缓存项是否存在,然后读取缓存项(注意:是读取EGOCache初始化的时候没有过期的缓存项,并没有说现在没有过期),最后去判断读取到的缓存项跟当前时间相比是否过期.
具体实现如下:
- (BOOL)hasCacheForKey:(NSString*)key {
//读取EGOCache初始化的时候没有过期的缓存项
NSDate* date = [self dateForKey:key];
if(date == nil) return NO;
//判断读取到的缓存项当前是否过期
if([date timeIntervalSinceReferenceDate] < CFAbsoluteTimeGetCurrent()) return NO;
return [[NSFileManager defaultManager] fileExistsAtPath:cachePathForKey(_directory, key)];
}
- (NSDate*)dateForKey:(NSString*)key {
__block NSDate* date = nil;
dispatch_sync(_frozenCacheInfoQueue, ^{
date = (self.frozenCacheInfo)[key];
});
return date;
}
EGOCache检测缓存时间过期的思路值得学习,以后遇到类似场景,完全可以借鉴。
JUL 1ST, 2015 12:10 AM
EGOCache是一个轻量级的缓存框架。用法简单方便,在现在的项目中,我就用到EGOCache来缓存下载过的照片和字符串。
有人可能会问到,缓存照片还需要用EGOCache吗?AFNetworking和SDWebImage不是已经有这些功能了吗?
是的,不过AFNetworking和SDWebImage是http。我的项目用的是socket,所以我选择EGOCache来做缓存。用下来觉得EGOCache还是挺强大的。
EGOCache is a simple, thread-safe key value cache store. It has native support for NSString, UI/NSImage, and NSData, but can store anything that implements <NSCoding>. All cached items expire after the timeout, which by default, is one day.
翻译过来就是:EGOCache一个简单、线程安全的基于 key-value 的缓存框架,原生支持NSString、UI/NSImage、和NSData,也支持储存任何实现协议的类,可以设定缓存过期时间,默认是1天。
EGOCache只有一个类,EGOCache.h和EGOCache.m两个文件。用法也比较容易掌握,仔细研究一下EGOCache.h的方法,很快就可以上手。
EGOCache只提供了磁盘缓存,没有提供内存缓存。同时,也提供了清理缓存的方法:
- (void)clearCache;
EGOCache还提供了判断缓存是否存在的方法:
- (BOOL)hasCacheForKey:(NSString* __nonnull)key;
直接在你的项目的Podfile加入下面一行:
pod ‘EGOCache‘
然后执行:
$ pod update
存储:
NSString *saveString = @"把我保存起来吧";
[[EGOCache globalCache] setString:saveString forKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[saveString hash]] withTimeoutInterval:24*60*60];
读取:
NSString *getSaveString = [[EGOCache globalCache] stringForKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveString" hash]]];
是不是感觉跟NSDictionary很相似,确实,前面我们说了EGOCache是基于key-value 的缓存框架。
存储:
UIImage *saveImage = [UIImage imageNamed:@"iOSDevTip"];
[[EGOCache globalCache] setImage:saveImage forKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveImage" hash]] withTimeoutInterval:24*60*60];
读取:
UIImage *getSaveImage = [[EGOCache globalCache] imageForKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveImage" hash]]];
存储:
NSData *saveData = [NSData data];
[[EGOCache globalCache] setData:saveData forKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveData" hash]] withTimeoutInterval:24*60*60];
读取:
UIImage *getSaveData = [[EGOCache globalCache] dataForKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveData" hash]]];
使用UIDataDetectorTypes自动检测电话、网址和邮箱
原文:http://www.cnblogs.com/dqbs/p/4656149.html