# iOS 知识小集#

2017-03-13  本文已影响121人  从容到没边的优雅

----采自博客or文章

<1> 如果我们想在控制台中输出视图的层级结构描述信息,可以使用UIView的私有方法recursiveDescription,如图1所示。这个方法在文档中找不到,在代码中调用也会报错。


<2> iOS10新变化---废弃的openURL
iOS 10之前用法:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]];```
options 字典参数,没有限定值就要传空字典:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];```
键:UIApplicationOpenURLOptionUniversalLinksOnly 字符串型,Value:true或 false
( 注:value 传Yes 或 No 有点糊涂,待大神解答再做完善...... )

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{UIApplicationOpenURLOptionUniversalLinksOnly : @NO} completionHandler:nil];

<3> 回顾下NSObject类的+load和+initialize这两个方法吧。
苹果文档
在程序启动时,Runtime会去加载所有的类。在这一时期,如果类或者类的分类实现了+load方法,则会去调用这个方法。

而+initialize方法是在类或子类第一次接收消息之前会被调用,这包括类的实例对象或者类对象。如果类一直没有被用到,则这个方法不会被调用。

基于这两个方法的特殊性,我们可以将类使用时所需要的一些前置条件在这两个方法中处理。不过,如果可能,应该尽量放在+initialize中。因为+load方法是在程序启动时调用,势必会影响到程序的启动时间。而+initialize方法可以说是懒加载调用,只有用到才会去执行。

<4> Apple在去年推出了Objective-C的几个新语言特性,其中一个是__kindof关键字。这个关键字的意思是指定的对象是类A或者其子类的实例。

我们可以看图1代码,在这种情况下,虽然array中有第一个元素是UIView 的实例,但编译器会给出警告,因为编译器认为array中存储的都是UIView 对象。

而如果我们用__kindof来修饰泛型类型,则编译器不会有警告,其认为array中存储的是UIView 或其子类的对象。

__kindof的提出应该与Objective-C泛型有很大关系,在系统库中存在很多这样的场景,如UIView的subviews属性,

参考链接:how to use __kindof in Objective-C

<5> 应该使用FOUNDATION_EXPORT还是#define来定义常量?

FOUNDATION_EXPORT NSString * const kMyConstantString; FOUNDATION_EXPORT NSString * const kMyConstantString2;
还有一种常用的#define方法
#define kMyConstantString @"Hello"

区别:
使用第一种方法在检测字符串的值是否相等的时候更快。对于第一种可以直接使用(stringInstance == MyFirstConstant)来比较,而define则使用的是这种([stringInstance isEqualToString:MyFirstConstant])。第一种直接比较的指针地址,而第二个则是逐项比较字符。

<6> 解决自定义返回按钮后侧边返回失效
self.navigationController.interactivePopGestureRecognizer.delegate = self;
这个api功能就是在NavigationController堆栈内的UIViewController可以支持右滑手势,
<7> iOS 网络请求URL包含中文转码的解决办法
ios9之前

NSString  *newUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  //该方法iOS 9 已经废弃了 但是如果你的项目需要兼容到iOS8或之前建议还是使用此方法

ios9之后

NSString  *newUrlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

<8> iOS 跳转到App store 评分 页面
换成自己的id号

  //https://itunes.apple.com/us/app/wo-zheng-ting-ju-ting-mei/id1146314461?l=zh&ls=1&mt=8
        NSString *str = [NSString stringWithFormat:@"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=%@",@"1146314461"];
        NSURL * url = [NSURL URLWithString:str];

        if ([[UIApplication sharedApplication] canOpenURL:url])
        {
            [[UIApplication sharedApplication] openURL:url];
        }
        else
        {
            NSLog(@"can not open");
        }

<9> iOS开发,UIButton怎样去掉高亮透明效果
要求:长按btn时(指的是按住btn不放),背景图和选中时的状态是一致的,但是试了各种方法都不行!
💊💊💊解决方法:
首先,创建一个button类,然后,重写setHighlighted方法,里面不用写任何东西;

- (void)setHighlighted:(BOOL)highlighted{

}

原文链接:http://www.jianshu.com/p/d3510be7ca95
<10>让滑动返回手势生效
如果使用自定义的按钮去替换系统默认返回按钮,会出现滑动返回手势失效的情况。解决方法也很简单,只需要重新添加导航栏的interactivePopGestureRecognizer的delegate即可。
首先为ViewContoller添加UIGestureRecognizerDelegate协议
然后设置代理
self.navigationController.interactivePopGestureRecognizer.delegate = self;

原文链接:http://www.jianshu.com/p/31f177158c9e

<11>图片写入相册薄

- (void)savePicToAlbum
{
    UIImageWriteToSavedPhotosAlbum([UIImage imageNamed:@""], self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
//此方法名随便写,不过传参必须一个不能少,否则报错
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    if (error) {
        
    }else{
        NSLog(@"save success!");
    }
}

<12>SDWebImage遗留问题(内存暴增)

- (void)viewDidLoad {
    //SDImageCache默认是利用NSCache存储资源,也就是利用内存。设置不使用内存就行
     [[SDImageCache sharedImageCache] setShouldCacheImagesInMemory:NO];
     [[SDImageCache sharedImageCache] setShouldDecompressImages:NO];
     [[SDImageCache sharedImageCache] setShouldCacheImagesInMemory:NO];
    
    // 设置内存最大 1M
    // The maximum length of time to keep an image in the cache, in seconds
     [[SDImageCache sharedImageCache] setMaxMemoryCost:1024 * 1024 * 1];
     [[SDImageCache sharedImageCache] setMaxCacheAge:3600 * 24 * 7];
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    [[SDImageCache sharedImageCache] clearMemory];
} 

<13> 在某些时候AFN提供的数据解析类型可能不够我们使用,比如某浪的数据结构"text/plain",AFN友好的给我们提供了acceptableContentTypes接口,所以,我们可以通过更改这个属性,添加我们要解析的类型到集合中

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// Request type
[manager.responseSerializer setAcceptableContentTypes:[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/css", @"text/plain",@"application/x-javascript", nil]];

<14>直接在xcode创建group会导致一个问题,在真正的项目文件里实际上并没有创建一个对应的文件夹。正确的做法如图:
(快捷键 command + option + a)


pic.gif

<15>for in遍历数组注意点:
最好不要试图在for in中对数组进行增删,采用常规的for循环

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSEnumerator_Class/index.html

You send nextObject repeatedly to a newly created NSEnumerator object to have it return the next object in the original collection. When the collection is exhausted, nil is returned. You cannot “reset” an enumerator after it has exhausted its collection. To enumerate a collection again, you need a new enumerator.
The enumerator subclasses used by NSArray, NSDictionary, and NSSet retain the collection during enumeration. When the enumeration is exhausted, the collection is released.

NOTE
It is not safe to modify a mutable collection while enumerating through it. Some enumerators may currently allow enumeration of a collection that is modified, but this behavior is not guaranteed to be supported in the future.

大概的意思是说,快速遍历的原理是根据enumerator对象内部的计数器,调用nextObject方法来实现返回下一个数组元素的,直到元素全部返回就会返回nil,于是整个enumerator对象就遍历完了;同时也提醒,以这种原理来遍历enumerator对象的话,无论对这个对象做什么操作,对象的计数器都不会被重置!
注意下面的NOTE,建议最好不要再快速遍历的时候修改enumerator,否则不保证是安全的.
原文链接:http://www.jianshu.com/p/a634310774a9

<16> xcode 自带颜色转换插件:Colors

colors.jpg

<17> 一句代码移除所有的子视图,非 for loop方法
---- 巧用数组对元素的操作

[view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

<18> 修改系统控件内部属性(runtime + KVC)
eg:UIPageControl指示器将圆点改成图片

2017-03-13 10:45:35.772 uipage[3295:378446] UIPageControl: _lastUserInterfaceIdiom
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _indicators
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _currentPage
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _displayedPage
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _pageControlFlags
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _currentPageImage  // 选中图片
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _pageImage  // 默认图片
2017-03-13 10:45:35.773 uipage[3295:378446] UIPageControl: _currentPageImages
2017-03-13 10:45:35.813 uipage[3295:378446] UIPageControl: _pageImages
2017-03-13 10:45:35.813 uipage[3295:378446] UIPageControl: _backgroundVisualEffectView
2017-03-13 10:45:35.813 uipage[3295:378446] UIPageControl: _currentPageIndicatorTintColor
2017-03-13 10:45:35.814 uipage[3295:378446] UIPageControl: _pageIndicatorTintColor
2017-03-13 10:45:35.814 uipage[3295:378446] UIPageControl: _legibilitySettings
2017-03-13 10:45:35.814 uipage[3295:378446] UIPageControl: _numberOfPages

19、桥接
__bridge type : 将CoreFoundation框架的对象所有权交给Foundation框架来使用,但是Foundation框架中的对象并不能管理该对象的内存。
__bridge_transfer Objective-C type : 将CoreFoundation框架的对象所有权交给Foundation来管理,如果Foundation中对象销毁,那么我们之前的对象(CoreFoundation)会一起销毁。

NSString *firstName = (__bridge NSString *)(firstname);  
NSString *lastName = (__bridge NSString *)(last name);
  /***---------------------------------***/
NSString *firstName = (__bridge_transfer NSString *)(firstname);  
NSString *lastName = (__bridge_transfer NSString *)(lastname);

20、IOS(SystemConfiguration)框架中关于测试连接网络状态相关方法

- (BOOL) connectedToNetwork
{
    //创建零地址,0.0.0.0的地址表示查询本机的网络连接状态
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;
    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;
    //获得连接的标志
    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);
    //如果不能获取连接标志,则不能连接网络,直接返回
    if (!didRetrieveFlags)
    {
        return NO;
    }
    //根据获得的连接标志进行判断
    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    return (isReachable && !needsConnection) ? YES : NO;
} 

21、检测设备是否为iPhone X/XS/系列
检测设备是否为 iPhone X/XS/XR 的几种方式
22、navi导航返回异常

1.gif
因为一直使用self.navigationController.navigationBarHidden或者self.navigationController.navigationBar.hidden来隐藏navigationBar

换成:[self.navigationController setNavigationBarHidden:YES animated:animated];带动画的处理方式就可以解决问题

23、iphone x tabbar 返回时布局错乱跳动
这个问题是 iOS 12.1 Beta 2 引入的问题,只要 UITabBar 是磨砂的,并且 push viewController 时 hidesBottomBarWhenPushed = YES 则手势返回的时候就会触发,出现这个现象的直接原因是 tabBar 内的按钮 UITabBarButton 被设置了错误的 frame,frame.size 变为 (0, 0) 导致的。
所以最简单的解决方案就是:
[UITabBar appearance].translucent = NO;
原文:https://blog.csdn.net/Longge_Li/article/details/83654333

上一篇下一篇

猜你喜欢

热点阅读