1.UIImageView尽量设置为不透明
opque尽量设置为YES
当UIImageView的opque设置为YES的时候其alpha的属性就会无效,UIImageView的半透明取决于其图片半透明或者UIImageView本身的背景色合成的图层view是半透明的。
如果图片全部不是半透明就不会触发图层的blend操作,整个图层就会不透明。
如果叠加的图片有出现半透明的,就会立马触发图层的blend操作,整个图层不透明。
背景色尽可能设为alpha值为1
当某一块图层的alpha和其superView的背景色alpha不一样的时候会触发alpha合成操作,这是一项看似很简单但却是非常消耗CPU性能的操作。
2.UIView的背景色设置
UIView的背景色尽量不要设置为clearColor,这样也会触发alpha叠加,在UITableView滑动的时候是非常消耗性能的。子视图的背景色尽可能设置成其superView的背景色,这样图层合成的时候不会触发blend操作。
最好不使用带alpha通道的图片,如果有alpha尽量让UI设计人员取消alpha通道。
3.cell上layer尽量避免使用圆角
在工作中关于滑动界面我们会时常遇到cell行设置头像为圆角等需求,这时候我们尽量避免使用layder.cornerRadius,因为这会触发离屏渲染。离屏渲染很耗时间。
离屏渲染:是GPU渲染区的一个渲染缓冲区,我们所用的所有显示屏的图形图像都是通过GPU进行渲染,然后显示在屏幕上。GPU负责渲染会把渲染的图形放到缓冲区然后CPU就会发一个垂直信号显示到屏幕。
如果要使用圆角,我们可以设置为layer.shouldRasterize = YES,其实这个设置是触发光栅化,可以大大提高渲染的性能。我的理解光栅化就是类似于cell的重用机制。
光栅化:把第一次渲染好的图层放到缓冲区,那么下次不需要再离屏渲染直接就可以从缓冲区拿去使用。
4.优化图片的加载方式
图片的加载方式有两种形式:
UIImageView *image = [UIImageView imageView:@"1.png"];
UIImageView *image = [UIImageView imageWithContentOfFile:@"1.png"];
两种加载图片方式的区别:
第一种:当我们经常需要这张图片并且仅仅是小图的时候,我们可以使用此种方式加载图片。
这种方式是把图片缓存在图片缓存区,当我们使用的时候会通过图片的名字也就是通过key的方式去查找图片在缓存区的内存地址。
当我们使用很多图片的时候系统就会开辟很多内存来存储图片,所以qq、微信我们很多时候都会去清除缓存操作。
第二种:当我们使用工程里面的一张大图并且使用次数很少甚至为1次的时候,我们优先会采用这种方式加载图片,这种方式当使用完图片的时候会立即丢弃释放资源,所以对性能不会带来负担。
5.尽量延迟图片的加载
当我们在滑动页面的时候尤其对于那种布局特别复杂的cell,滑动的时候不要加载图片,当滑动停止得时候再进行图片的加载。
我们都知道不管是UITableView还是UIScrollView在滚动的时候需要显示东西都是通过runLoop去拿。
当滚动的时候runLoop会处于NSRunLoopTrackingMode的模式,我们可以通过一个主线程队列dispatch_after或者selfPerformSelector设置runLoop的模式为NSDefaultRunLoopMode模式,就可以做到停止滚动再加载图片。
注:其实严格意义上selfPerformSelector的事件就是在主线程队列中等待。
优先加载理念
采用优先加载的理念,既先展示一部分,当滑动的时候再加载下面的一部分这样就保持流畅。
6.去除UISearchbar边框,换掉UISearchbar的背景图片即可
UIImageView *imageView =[[UIImageView alloc] initWithImage:[UIImageimageNamed:@"searchBarBGImage"]];
self.searchBar.backgroundImage =imageView.image;
7.修改搜索输入文本的背景
[_searchBar setSearchFieldBackgroundImage:[UIImageimageNamed:@"login_btn_input_side.png"]forState:UIControlStateNormal];
8.UITextField不显示光标
textField.tintColor=[UIColor clearColor];
9.修改UITextField中Placeholder的文字颜色
[textField setValue:[UIColor redColor]forKeyPath:@"_placeholderLabel.textColor"];
10..UITableView隐藏多余的cell
tableview.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
11.UITableView在plane模式下让section头部不停留,在scrollViewDidScroll方法里面写
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat sectionHeaderHeight =25;//头部的高度
if(scrollView.contentOffset.y <= sectionHeaderHeight &&scrollView.contentOffset.y> 0) {
scrollView.contentInset= UIEdgeInsetsMake(- scrollView.contentOffset.y, 0, 0, 0);
}else{
if(scrollView.contentOffset.y >=sectionHeaderHeight){
scrollView.contentInset=UIEdgeInsetsMake(-sectionHeaderHeight,0,0,0);
}
}
}
12.UITableView的Group样式下顶部空白处理
//分组列表头部空白处理
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, 0.1)];
self.tableView.tableHeaderView = view;
13.两种方法删除NSUserDefaults所有记录
//方法一
NSString *appDomain = [[NSBundle mainBundle]bundleIdentifier];
[[NSUserDefaults standardUserDefaults]removePersistentDomainForName:appDomain];
//方法二
- (void)resetDefaults
{
NSUserDefaults * defs = [NSUserDefaultsstandardUserDefaults];
NSDictionary * dict = [defs dictionaryRepresentation];
for (id key in dict)
{
[defs removeObjectForKey:key];
}
[defs synchronize];
}
14.iOS 获取汉字的拼音
+ (NSString *)transform:(NSString *)chinese
{
//将NSString装换成NSMutableString
NSMutableString *pinyin = [chinese mutableCopy];
//将汉字转换为拼音(带音标)
CFStringTransform((__bridge CFMutableStringRef)pinyin,NULL, kCFStringTransformMandarinLatin, NO);
NSLog(@"%@", pinyin);
//去掉拼音的音标
CFStringTransform((__bridge CFMutableStringRef)pinyin,NULL, kCFStringTransformStripCombiningMarks, NO);
NSLog(@"%@", pinyin);
//返回最近结果
return pinyin;
}
15.手动更改iOS状态栏的颜色
- (void)setStatusBarBackgroundColor:(UIColor *)color
{
UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"]valueForKey:@"statusBar"];
if ([statusBarrespondsToSelector:@selector(setBackgroundColor:)])
{
statusBar.backgroundColor = color;
}
}
16.判断当前ViewController是push还是present的方式显示的
NSArray *viewcontrollers=self.navigationController.viewControllers;
if (viewcontrollers.count > 1)
{
if ([viewcontrollers objectAtIndex:viewcontrollers.count- 1] == self)
{
//push方式
[self.navigationControllerpopViewControllerAnimated:YES];
}
}
else
{
//present方式
[self dismissViewControllerAnimated:YES completion:nil];
}
17.GCD timer倒计时定时器
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0, 0,queue);
dispatch_source_set_timer(timer,dispatch_walltime(NULL,0),1.0*NSEC_PER_SEC, 0); //每秒执行
dispatch_source_set_event_handler(timer, ^{
//@"倒计时结束,关闭"
dispatch_source_cancel(timer);
dispatch_async(dispatch_get_main_queue(), ^{
});
});
dispatch_resume(timer);
18.导航栏设置
1.改变导航栏标题颜色
self.navigationItem.rightBarButtonItem.tintColor =[UIColor whiteColor];
[self.navigationController.navigationBarsetTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColorwhiteColor]}];
2.改变导航栏背景颜色
[self.navigationController.navigationBarsetBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBarsetShadowImage:[UIImage new]];
[self.navigationController.navigationBarsetBarTintColor:[UIColor colorWithRed:128/255.0f green:128/255.0fblue:128/255.0f alpha:1]];
19.调整行间距
NSMutableAttributedString *attributedString =[[NSMutableAttributedString alloc] initWithString:self.ruleLabel.text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStylealloc] init];
[paragraphStylesetLineSpacing:10];
[attributedStringaddAttribute:NSParagraphStyleAttributeName value:paragraphStylerange:NSMakeRange(0, [self.ruleLabel.text length])];
20.用代码计算文字的宽高
-(CGSize)sizeWithText:(NSString *)text font:(UIFont*)font maxW:(CGFloat)maxW
{
NSMutableDictionary *attrs=[NSMutableDictionary dictionary];
attrs[NSFontAttributeName]=font;
CGSizemaxSize=CGSizeMake(maxW, MAXFLOAT);
return [textboundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOriginattributes:attrs context:nil].size;
}
21.禁止锁屏
默认情况下,当设备一段时间没有触控动作时,iOS会锁住屏幕。但有一些应用是不需要锁屏的,比如视频播放器。
[UIApplication sharedApplication].idleTimerDisabled = YES;
或
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
22.字符串反转
第一种:
- (NSString *)reverseWordsInString:(NSString *)str
{
NSMutableString *newString = [[NSMutableString alloc] initWithCapacity:str.length];
for(NSInteger i = str.length - 1; i >= 0 ; i --)
{
unichar ch = [str characterAtIndex:i];
[newString appendFormat:@"%c", ch];
}
returnnewString;
}
//第二种:
- (NSString*)reverseWordsInString:(NSString*)str
{
NSMutableString *reverString = [NSMutableString stringWithCapacity:str.length];
[str enumerateSubstringsInRange:NSMakeRange(0, str.length) options:NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[reverString appendString:substring];
}];
returnreverString;
}
23.字符串按多个符号分割
NSString *str = @"abc,def.ghij";
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@",."];
NSLog(@"%@",[str componentsSeparatedByCharactersInSet:set]);
24.iOS跳转到App Store下载应用评分
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APPID"]];
25.iOS 获取汉字的拼音
+ (NSString *)transform:(NSString *)chinese
{
//将NSString装换成NSMutableString
NSMutableString *pinyin = [chinese mutableCopy];
//将汉字转换为拼音(带音标)
CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformMandarinLatin, NO);
NSLog(@"%@", pinyin);
//去掉拼音的音标
CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformStripCombiningMarks, NO);
NSLog(@"%@", pinyin);
//返回最近结果
returnpinyin;
}
26.手动更改iOS状态栏的颜色
- (void)setStatusBarBackgroundColor:(UIColor *)color
{
UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
if([statusBar respondsToSelector:@selector(setBackgroundColor:)])
{
statusBar.backgroundColor = color;
}
}
27.判断当前ViewController是push还是present的方式显示的
NSArray *viewcontrollers=self.navigationController.viewControllers;
if(viewcontrollers.count > 1)
{
if([viewcontrollers objectAtIndex:viewcontrollers.count - 1] == self)
{
//push方式
[self.navigationController popViewControllerAnimated:YES];
}
}
else
{
//present方式
[self dismissViewControllerAnimated:YES completion:nil];
}
28.获取实际使用的LaunchImage图片
- (NSString *)getLaunchImageName
{
CGSize viewSize = self.window.bounds.size;
// 竖屏
NSString *viewOrientation = @"Portrait";
NSString *launchImageName = nil;
NSArray* imagesDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
for(NSDictionary* dict inimagesDict)
{
CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]);
if(CGSizeEqualToSize(imageSize, viewSize) && [viewOrientation isEqualToString:dict[@"UILaunchImageOrientation"]])
{
launchImageName = dict[@"UILaunchImageName"];
}
}
returnlaunchImageName;
}
29.iOS在当前屏幕获取第一响应
UIWindow * keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView * firstResponder = [keyWindow performSelector:@selector(firstResponder)];
30.判断对象是否遵循了某协议
if([self.selectedController conformsToProtocol:@protocol(RefreshPtotocol)])
{
[self.selectedController performSelector:@selector(onTriggerRefresh)];
}
31.判断view是不是指定视图的子视图
BOOL isView = [textView isDescendantOfView:self.view];
32.NSArray 快速求总和 最大值 最小值 和 平均值
NSArray *array = [NSArray arrayWithObjects:@"2.0", @"2.3", @"3.0", @"4.0", @"10", nil];
CGFloat sum = [[array valueForKeyPath:@"@sum.floatValue"] floatValue];
CGFloat avg = [[array valueForKeyPath:@"@avg.floatValue"] floatValue];
CGFloat max =[[array valueForKeyPath:@"@max.floatValue"] floatValue];
CGFloat min =[[array valueForKeyPath:@"@min.floatValue"] floatValue];
NSLog(@"%f\n%f\n%f\n%f",sum,avg,max,min);
33.修改UITextField中Placeholder的文字颜色和字体大小
[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
[self.textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@"_placeholderLabel.font"];
34.关于NSDateFormatter的格式
G: 公元时代,例如AD公元
yy: 年的后2位
yyyy: 完整年
MM: 月,显示为1-12
MMM: 月,显示为英文月份简写,如 Jan
MMMM: 月,显示为英文月份全称,如 Janualy
dd: 日,2位数表示,如02
d: 日,1-2位显示,如 2
EEE: 简写星期几,如Sun
EEEE: 全写星期几,如Sunday
aa: 上下午,AM/PM
H: 时,24小时制,0-23
K:时,12小时制,0-11
m: 分,1-2位
mm: 分,2位
s: 秒,1-2位
ss: 秒,2位
S: 毫秒
35.获取一个类的所有子类
+ (NSArray *) allSubclasses
{
Class myClass = [self class];
NSMutableArray *mySubclasses = [NSMutableArray array];
unsigned int numOfClasses;
Class *classes = objc_copyClassList(&numOfClasses;);
for(unsigned int ci = 0; ci ( numOfClasses; ci++)
{
Class superClass = classes[ci];
do{
superClass = class_getSuperclass(superClass);
} while(superClass && superClass != myClass);
if(superClass)
{
[mySubclasses addObject: classes[ci]];
}
}
free(classes);
returnmySubclasses;
}
36.监测IOS设备是否设置了代理,需要CFNetwork.framework
NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:@"http://www.baidu.com"]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));
NSLog(@"\n%@",proxies);
NSDictionary *settings = proxies[0];
NSLog(@"%@",[settings objectForKey:(NSString *)kCFProxyHostNameKey]);
NSLog(@"%@",[settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
NSLog(@"%@",[settings objectForKey:(NSString *)kCFProxyTypeKey]);
if([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"])
{
NSLog(@"没代理");
}
else
{
NSLog(@"设置了代理");
}
37.阿拉伯数字转中文格式
+(NSString *)translation:(NSString *)arebic
{
NSString *str = arebic;
NSArray *arabic_numerals = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"0"];
NSArray *chinese_numerals = @[@"一",@"二",@"三",@"四",@"五",@"六",@"七",@"八",@"九",@"零"];
NSArray *digits = @[@"个",@"十",@"百",@"千",@"万",@"十",@"百",@"千",@"亿",@"十",@"百",@"千",@"兆"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:chinese_numerals forKeys:arabic_numerals];
NSMutableArray *sums = [NSMutableArray array];
for(int i = 0; i ( str.length; i ++) {
NSString *substr = [str substringWithRange:NSMakeRange(i, 1)];
NSString *a = [dictionary objectForKey:substr];
NSString *b = digits[str.length -i-1];
NSString *sum = [a stringByAppendingString:b];
if([a isEqualToString:chinese_numerals[9]])
{
if([b isEqualToString:digits[4]] || [b isEqualToString:digits[8]])
{
sum = b;
if([[sums lastObject] isEqualToString:chinese_numerals[9]])
{
[sums removeLastObject];
}
}else
{
sum = chinese_numerals[9];
}
if([[sums lastObject] isEqualToString:sum])
{
continue;
}
}
[sums addObject:sum];
}
NSString *sumStr = [sums componentsJoinedByString:@""];
NSString *chinese = [sumStr substringToIndex:sumStr.length-1];
NSLog(@"%@",str);
NSLog(@"%@",chinese);
returnchinese;
}
38.Base64编码与NSString对象或NSData对象的转换
// Create NSData object
NSData *nsdata = [@"iOS Developer Tips encoded in Base64"
dataUsingEncoding:NSUTF8StringEncoding];
// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
// Print the Base64 encoded string
NSLog(@"Encoded: %@", base64Encoded);
// Let's go the other way...
// NSData from the Base64 encoded str
NSData *nsdataFromBase64String = [[NSData alloc]
initWithBase64EncodedString:base64Encoded options:0];
// Decoded NSString from the NSData
NSString *base64Decoded = [[NSString alloc]
initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];
NSLog(@"Decoded: %@", base64Decoded);
39.CocoaPods pod install/pod update更新慢的问题
pod install --verbose --no-repo-update
pod update --verbose --no-repo-update
如果不加后面的参数,默认会升级CocoaPods的spec仓库,加一个参数可以省略这一步,然后速度就会提升不少
40.UIImage 占用内存大小
UIImage *image = [UIImage imageNamed:@"aa"];
NSUInteger size = CGImageGetHeight(image.CGImage) * CGImageGetBytesPerRow(image.CGImage);
41.GCD timer定时器
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
dispatch_source_set_event_handler(timer, ^{
//@"倒计时结束,关闭"
dispatch_source_cancel(timer);
dispatch_async(dispatch_get_main_queue(), ^{
});
});
dispatch_resume(timer);
42.图片上绘制文字 写一个UIImage的category
- (UIImage *)imageWithTitle:(NSString *)title fontSize:(CGFloat)fontSize
{
//画布大小
CGSize size=CGSizeMake(self.size.width,self.size.height);
//创建一个基于位图的上下文
UIGraphicsBeginImageContextWithOptions(size,NO,0.0);//opaque:NO scale:0.0
[self drawAtPoint:CGPointMake(0.0,0.0)];
//文字居中显示在画布上
NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
paragraphStyle.alignment=NSTextAlignmentCenter;//文字居中
//计算文字所占的size,文字居中显示在画布上
CGSize sizeText=[title boundingRectWithSize:self.size options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}context:nil].size;
CGFloat width = self.size.width;
CGFloat height = self.size.height;
CGRect rect = CGRectMake((width-sizeText.width)/2, (height-sizeText.height)/2, sizeText.width, sizeText.height);
//绘制文字
[title drawInRect:rect withAttributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:fontSize],NSForegroundColorAttributeName:[ UIColor whiteColor],NSParagraphStyleAttributeName:paragraphStyle}];
//返回绘制的新图形
UIImage *newImage= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
returnnewImage;
}
43.UIView设置部分圆角
你是不是也遇到过这样的问题,一个button或者label,只要右边的两个角圆角,或者只要一个圆角。该怎么办呢。这就需要图层蒙版来帮助我们了
CGRect rect = view.bounds;
CGSize radio = CGSizeMake(30, 30);//圆角尺寸
UIRectCorner corner = UIRectCornerTopLeft|UIRectCornerTopRight;//这只圆角位置
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corner cornerRadii:radio];
CAShapeLayer *masklayer = [[CAShapeLayer alloc]init];//创建shapelayer
masklayer.frame = view.bounds;
masklayer.path = path.CGPath;//设置路径
view.layer.mask = masklayer;
44.给UIView设置图片
UIImage *image = [UIImage imageNamed:@"image"];
self.MYView.layer.contents = (__bridge id _Nullable)(image.CGImage);
self.MYView.layer.contentsRect = CGRectMake(0, 0, 0.5, 0.5);
45.防止scrollView手势覆盖侧滑手势
[scrollView.panGestureRecognizerrequireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer];
46.去掉导航栏返回的back标题
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)forBarMetrics:UIBarMetricsDefault];
47.字符串中是否含有中文
+ (BOOL)checkIsChinese:(NSString *)string
{
for(int i=0; i(string.length; i++)
{
unichar ch = [string characterAtIndex:i];
if(0x4E00 (= ch && ch (= 0x9FA5)
{
returnYES;
}
}
returnNO;
}
48.dispatch_group的使用
dispatch_group_t dispatchGroup = dispatch_group_create();
dispatch_group_enter(dispatchGroup);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"第一个请求完成");
dispatch_group_leave(dispatchGroup);
});
dispatch_group_enter(dispatchGroup);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"第二个请求完成");
dispatch_group_leave(dispatchGroup);
});
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
NSLog(@"请求完成");
});
49.UITextField每四位加一个空格,实现代理
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// 四位加一个空格
if([string isEqualToString:@""])
{
// 删除字符
if((textField.text.length - 2) % 5 == 0)
{
textField.text = [textField.text substringToIndex:textField.text.length - 1];
}
returnYES;
}
else
{
if(textField.text.length % 5 == 0)
{
textField.text = [NSString stringWithFormat:@"%@ ", textField.text];
}
}
returnYES;
}
50.获取私有属性和成员变量 #import
//获取私有属性 比如设置UIDatePicker的字体颜色
- (void)setTextColor
{
//获取所有的属性,去查看有没有对应的属性
unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([UIDatePicker class], &count);
for(int i = 0;i ( count;i ++)
{
//获得每一个属性
objc_property_t property = propertys[i];
//获得属性对应的nsstring
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
//输出打印看对应的属性
NSLog(@"propertyname = %@",propertyName);
if([propertyName isEqualToString:@"textColor"])
{
[datePicker setValue:[UIColor whiteColor] forKey:propertyName];
}
}
}
//获得成员变量 比如修改UIAlertAction的按钮字体颜色
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([UIAlertAction class], &count);
for(int i =0;i ( count;i ++)
{
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
NSLog(@"uialertion.ivarName = %@",ivarName);
if([ivarName isEqualToString:@"_titleTextColor"])
{
[alertOk setValue:[UIColor blueColor] forKey:@"titleTextColor"];
[alertCancel setValue:[UIColor purpleColor] forKey:@"titleTextColor"];
}
}
51.应用内打开系统设置界面
//iOS8之后
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
//iOS8之前
//先添加一个url type如下图,在代码中调用如下代码,即可跳转到设置页面的对应项
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]];
可选值如下:
About — prefs:root=General&path=About
Accessibility — prefs:root=General&path=ACCESSIBILITY
Airplane Mode On — prefs:root=AIRPLANE_MODE
Auto-Lock — prefs:root=General&path=AUTOLOCK
Brightness — prefs:root=Brightness
Bluetooth — prefs:root=General&path=Bluetooth
Date & Time — prefs:root=General&path=DATE_AND_TIME
FaceTime — prefs:root=FACETIME
General — prefs:root=General
Keyboard — prefs:root=General&path=Keyboard
iCloud — prefs:root=CASTLE
iCloud Storage & Backup — prefs:root=CASTLE&path=STORAGE_AND_BACKUP
International — prefs:root=General&path=INTERNATIONAL
Location Services — prefs:root=LOCATION_SERVICES
Music — prefs:root=MUSIC
Music Equalizer — prefs:root=MUSIC&path=EQ
Music Volume Limit — prefs:root=MUSIC&path=VolumeLimit
Network — prefs:root=General&path=Network
Nike + iPod — prefs:root=NIKE_PLUS_IPOD
Notes — prefs:root=NOTES
Notification — prefs:root=NOTIFICATI*****_ID
Phone — prefs:root=Phone
Photos — prefs:root=Photos
Profile — prefs:root=General&path=ManagedConfigurationList
Reset — prefs:root=General&path=Reset
Safari — prefs:root=Safari
Siri — prefs:root=General&path=Assistant
Sounds — prefs:root=Sounds
Software Update — prefs:root=General&path=SOFTWARE_UPDATE_LINK
Store — prefs:root=STORE
Twitter — prefs:root=TWITTER
Usage — prefs:root=General&path=USAGE
VPN — prefs:root=General&path=Network/VPN
Wallpaper — prefs:root=Wallpaper
Wi-Fi — prefs:root=WIFI
52.如何获取WebView所有的图片地址
//UIWebView
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//这里是js,主要目的实现对url的获取
static NSString * const jsGetImages =
@"functiongetImages(){\
varobjs = document.getElementsByTagName(\"img\");\
varimgScr = '';\
for(vari=0;i(objs.length;i++){\
imgScr = imgScr + objs[i].src + '+';\
};\
returnimgScr;\
};";
[webView stringByEvaluatingJavaScriptFromString:jsGetImages];//注入js方法
NSString *urlResult = [webView stringByEvaluatingJavaScriptFromString:@"getImages()"];
NSArray *urlArray = [NSMutableArray arrayWithArray:[urlResult componentsSeparatedByString:@"+"]];
//urlResurlt 就是获取到得所有图片的url的拼接;mUrlArray就是所有Url的数组
}
//WKWebView
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
{
static NSString * const jsGetImages =
@"functiongetImages(){\
varobjs = document.getElementsByTagName(\"img\");\
varimgScr = '';\
for(vari=0;i(objs.length;i++){\
imgScr = imgScr + objs[i].src + '+';\
};\
returnimgScr;\
};";
[webView evaluateJavaScript:jsGetImages completionHandler:nil];
[webView evaluateJavaScript:@"getImages()"completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@",result);
}];
}
53.获取到webview的高度
CGFloat height = [[self.webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];
54.navigationBar变为纯透明
//第一种方法
//导航栏纯透明
[self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
//去掉导航栏底部的黑线
self.navigationBar.shadowImage = [UIImage new];
//第二种方法
[[self.navigationBar subviews] objectAtIndex:0].alpha = 0;
tabBar同理
[self.tabBar setBackgroundImage:[UIImage new]];
self.tabBar.shadowImage = [UIImage new];
55.navigationBar根据滑动距离的渐变色实现
//第一种
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetToShow = 200.0;//滑动多少就完全显示
CGFloat alpha = 1 - (offsetToShow - scrollView.contentOffset.y) / offsetToShow;
[[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = alpha;
}
//第二种
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetToShow = 200.0;
CGFloat alpha = 1 - (offsetToShow - scrollView.contentOffset.y) / offsetToShow;
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
[self.navigationController.navigationBar setBackgroundImage:[self imageWithColor:[[UIColor orangeColor]colorWithAlphaComponent:alpha]] forBarMetrics:UIBarMetricsDefault];
}
//生成一张纯色的图片
- (UIImage *)imageWithColor:(UIColor *)color
{
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
returntheImage;
}
56.NSString进行URL编码和解码
NSString *string = @"http://abc.com?aaa=你好&bbb=tttee";
//编码 打印:http://abc.com?aaa=%E4%BD%A0%E5%A5%BD&bbb=tttee
string = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//解码 打印:http://abc.com?aaa=你好&bbb=tttee
string = [string stringByRemovingPercentEncoding];
57.获取硬盘总容量与可用容量
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *attributes = [fileManager attributesOfFileSystemForPath:NSHomeDirectory() error:nil];
1
NSLog(@"容量%.2fG",[attributes[NSFileSystemSize] doubleValue] / (powf(1024, 3)));
NSLog(@"可用%.2fG",[attributes[NSFileSystemFreeSize] doubleValue] / powf(1024, 3));
58.AFN移除JSON中的NSNull
AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];
response.removesKeysWithNullValues = YES;
59.UIWebView里面的图片自适应屏幕
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *js = @"functionimgAutoFit() { \
varimgs = document.getElementsByTagName('img'); \
for(vari = 0; i ( imgs.length; ++i) { \
varimg = imgs[i]; \
img.style.maxWidth = %f; \
} \
}";
js = [NSString stringWithFormat:js, [UIScreen mainScreen].bounds.size.width - 20];
[webView stringByEvaluatingJavaScriptFromString:js];
[webView stringByEvaluatingJavaScriptFromString:@"imgAutoFit()"];
}
60.CALayer如何添加点击事件
两种方法: convertPoint和hitTest:,hitTest: 返回的顺序严格按照图层树的图层顺序。
第一种方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{
CGPointpoint = [[touches anyObject] locationInView:self.view];
CGPointredPoint = [self.redLayer convertPoint:point fromLayer:self.view.layer];
if([self.redLayer containsPoint:redPoint]) {
UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"point red"message:@""delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:nil];
[alert show];
}
}
第二种方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{
CGPointpoint = [[touches anyObject] locationInView:self.view];
CALayer*layer = [self.view.layer hitTest:point];
if(layer ==self.redLayer) {
UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"point red"message:@""delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:nil];
[alert show];
}elseif(layer ==self.yellowLayer){
UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"point yellow"message:@""delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:nil]; [alert show];
}
}
61.如何对 NSMutableArray 进行 KVO
一般情况下只有通过调用 set 方法对值进行改变才会触发 KVO。但是在调用NSMutableArray的 addObject或removeObject 系列方法时,并不会触发它的 set 方法。所以为了实现NSMutableArray的 KVO,官方为我们提供了如下方法:
- (NSMutableArray*)mutableArrayValueForKey:(NSString*)key;
在增删元素时,使用上述方法来获取要操作的可变数组,然后再执行添加或删除元素的操作,便能实现 KVO 机制。如:
@property(nonatomic,strong)NSMutableArray*arr;
//添加元素操作
[[self mutableArrayValueForKey:@"arr"] addObject:item];
//移除元素操作
[[self mutableArrayValueForKey:@"arr"] removeObjectAtIndex:0];
62.被忽略的UIViewController两对API
如何判断一个页面的viewWillAppear方法是 push 或 present 进来是调用的,还是 pop 或 dismiss 是调用的?一种比较笨拙的方法是通过添加属性标记是进入还是返回调用viewWillAppear方法。还有一种最简单的方法,是直接调用苹果提供的两对 API 。
针对 Push 和 Pop 或 add childViewController 和 remove childViewController 的 API:
@property(nonatomic,readonly,getter=isMovingToParentViewController)BOOL movingToParentViewControllerNS_AVAILABLE_IOS(5_0);
@property(nonatomic,readonly,getter=isMovingFromParentViewController)BOOL movingFromParentViewControllerNS_AVAILABLE_IOS(5_0);
针对 Present 和 Dismiss 的 API:
@property(nonatomic,readonly,getter=isBeingPresented)BOOL beingPresentedNS_AVAILABLE_IOS(5_0);
@property(nonatomic,readonly,getter=isBeingDismissed)BOOL beingDismissedNS_AVAILABLE_IOS(5_0);
63.为什么数组下标从零开始
数组下标最确切的定义应该偏移(offset),如果用 a 来表示数组的首地址,a[0] 就是偏移为 0 的位置,也就是首地址,a[k] 就表示偏移 k 个 type_size 的位置,所以计算 a[k] 的内存地址只需要用这个公式:
a[k]_address = base_address + k * type_size
但是,如果数组从 1 开始计数,那我们计算数组元素 a[k]的内存地址就会变为:
a[k]_address = base_address + (k-1)*type_size
对比两个公式,不难发现,从 1 开始编号,每次随机访问数组元素都多了一次减法运算,对于 CPU 来说,就是多了一次减法指令。数组作为非常基础的数据结构,通过下标随机访问数组元素又是其非常基础的编程操作,效率的优化就要尽可能做到极致。所以为了减少一次减法操作,数组选择了从 0 开始编号,而不是从 1 开始。
64.weak 原理说明
一个对象可能会被多次弱引用,当这个对象被销毁时,我们需要找到这个对象的所有弱引用,所以我们需要将这些弱引用的地址(即指针)放在一个容器里(比如数组)。当对象不再被强引用时需要销毁的时候,可以在SideTable中 通过这个对象的地址找到引用值,清空引用值。同时,SideTable结构中还有weak_table_t结构,该结构也是一个散列表,key 为对象地址,value 为一个数组,里面保存着指向该对象的所有弱指针。当对象释放的时候,先清空引用哈希表RefcountMap对应的引用值,遍历弱指针数组,依次将各个弱指针置为 nil。
65.IP 和 MAC
IP 是地址,有定位功能;MAC 是身份唯一标识,无定位功能;有了 MAC 地址为什么还要有 IP 地址?举个例子,现在我要和你通信(写信给你),地址用你的身份证号,信能送到你手上吗? 明显不能!身份证号前六位能定位你出生的县,MAC 地址前几位也可以定位生产厂家。但是你出生后会离开这个县(IP 地址变动),哪怕你还在这个县,我总不能满大街喊着你的身份证号去问路边人是否认识这个身份证号的主人,所以此刻需要借助 IP 的定位功能。
66.App 启动流程
APP 启动分为冷启动和热启动,这里主要说下冷启动过程。冷启动分为三阶段: dyld 阶段、runtime阶段、main函数阶段,一般启动时间的优化也是从这三大步着手。
1.dyld阶段:dyld(dynamic link editor)是Apple的动态链接器,可以用来装载 Mach-O 文件(可执行文件、动态库等)。启动APP时,dyld 首先装载可执行文件,同时会递归加载所有依赖的动态库。
2.runtime 阶段:首先解析可执行文件,之后调用所有类和分类的+load方法,并进行各种objc结构的初始化(注册Objc类 、初始化类对象等等)。到此为止,可执行文件和动态库中所有的符号(Class、Protocol、Selector、IMP …)都已经按格式成功加载到内存中,被runtime 所管理。
3.main函数阶段:所有初始化工作结束后,dyld就会调用main函数。