iOS开发常用知识点

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<objc/runtime.h>

//获取私有属性 比如设置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


iOS8之后需添加

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函数。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容