美文网首页
一些知识点

一些知识点

作者: Alfred的记录本 | 来源:发表于2017-06-27 00:14 被阅读0次

1.

clipsToBounds:是指视图上的子视图,如果超出父视图的部分就截取掉,
masksToBounds:是指视图的图层上的子图层,如果超出父图层的部分就截取掉

2.

// NSArray --> NSMutableArray  
NSMutableArray *myMutableArray = [myArray mutableCopy];  
  
// NSMutableArray --> NSArray  
NSArray *myArray = [myMutableArray copy];

3.

1.自定义cell时,
若使用nib,使用 registerNib: 注册,dequeue时会调用 cell 的 -
(void)awakeFromNib
不使用nib,使用 registerClass: 注册, dequeue时会调用 cell 的 - (id)initWithStyle:withReuseableCellIdentifier:
2.需不需要注册?
使用dequeueReuseableCellWithIdentifier:可不注册,但是必须对获取回来的cell进行判断是否为空,若空则手动创建新的cell;
使用dequeueReuseableCellWithIdentifier:forIndexPath:必须注册,但返回的cell可省略空值判断的步骤。

4.

如果该类没有ViewController

[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];

5.字典和实体类的转换

[self setValuesForKeysWithDictionary:dict];

6.delegate block属性的关键字

  • 为了防止循环引用,delegate的关键字使用weak
  • block作为类的属性时用copy
    Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的
    <栈 :由系统维护的局部变量 是存在栈上的,其生命周期随函数的生命周期>
    <堆 :由程序员申请空间地址,由程序员手动释放,生命周期受到程序员控制>
    使用retain也可以,因为block的retain行为默认是用copy的行为实现的,block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。
    另一个需要注意的问题是关于线程安全,在声明Block属性时需要确认“在调用Block时另一个线程有没有可能去修改Block?”这个问题,如果确定不会有这种情况发生的话,那么Block属性声明可以用nonatomic。如果不肯定的话(通常情况是这样的),那么你首先需要声明Block属性为atomic,也就是先保证变量的原子性(Objective-C并没有强制规定指针读写的原子性)。
    参考

7.隐藏UITableBar

当页面使用 UITabBarController + UINavigationController 框架的时候,当跳转到详情页面的时候,如果 UITabBar 仍然存在的话就会造成逻辑混乱,用户体验也会下降,因此我们就有一个在详情页将 UITabBar 隐藏的需求,参考链接

  • self.hidesBottomBarWhenPushed = YES;
  • self.tabBarController.tabBar.hidden = NO;
  • 修改 TabBar 的 subview 的 frame

8. id的使用

id <SDWebImageOperation> operation

9. runtime动态添加属性

10. 自定义NSOperation

11.NSURLSession

12.KVO KVC

  • kvo的用法非常简单。
    1,添加观察者
    2,在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:(通过查阅文档可以知道,绝大多数对象都有这个方法,因为这个方法属于NSObject)
    3,移除观察者

  • 修改成员变量不会触发监听器,只有修改属性值才行。
    例如
    self.changeHeight = self.frame.size.height;//能触发
    _changeHeight = self.frame.size.height;//不能触发
    参考链接

  • 手动KVO

    [self willChangeValueForKey:@"changeHeight"];
    _changeHeight = self.frame.size.height;
    [self didChangeValueForKey:@"changeHeight"];
  • 禁用自动KVO
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
    if ([theKey isEqualToString:@"changeHeight"]) {
        return NO;
    } else {
        return [super automaticallyNotifiesObserversForKey:theKey];
    }
}

13.HTTPS 验证

14.网络缓存

网络缓存

15.NSURLCache

参考链接

16.extern const static

参考链接

  • extern 用法
    • a.m 文件中定义
#import "a.h"
NSString * const strExtern = @"strExtern";
  • a.h文件中声明
    extern NSString * const strExtern;

  • b.m 文件对外部变量进行引用

#import "a.h"
NSLog(@"strExtern : %@", strExtern);
  • const 用法
    • 声明字符串常量
      NSString * const strExtern = @"strExtern";
    • 以下声明方式的区别
NSString * const strExtern = @"strExtern";//指针指向的地址(strExtern)不可变
const NSString *strExtern = @"strExtern";//字符串内容(*strExtern)不可变
  • static 用法
    如果定义在.m文件中则不能对外使用,只能本文件使用
static NSString * const strExtern = @"strExtern";

16. __nullable和 __nonnull

苹果在Xcode 6.3引入了一个Objective-C的新特性:nullability annotations。这一新特性的核心是两个新的类型注释:__nullable和__nonnull。从字面上我们可以猜到,__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。

17. delegate block 的修饰符

18. block 引起的循环引用

某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,即使在你的block代码中没有显式地出现"self",也会出现循环引用!只要你在block里用到了self所拥有的东西!简单说就是

self.someBlock = ^(Type var){
  [self dosomething];
  或者self.otherVar = XXX;
  或者_otherVar = ...
}
  • 解决方法
__weak typeof(self) weakSelf = self;
self.blkA = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;//加一下强引用,避免weakSelf被释放掉
NSLog(@"%@", strongSelf->_xxView); //不会导致循环引用.
};
  • 总结

分两种环境去解决:
1)ARC环境下:ARC环境下可以通过使用_weak声明一个代替self的新变量代替原先的self,我们可以命名为weakSelf。通过这种方式告诉block,不要在block内部对self进行强制strong引用:(如果要兼容ios4.3,则用__unsafe_unretained代替__weak,不过目前基本不需考虑这么low的版本)

          self.arr = @[@111, @222, @333];
         __weak typeof(self) weakSelf=self;
         self.block = ^(NSString *name){
             NSLog(@"arr:%@", weakSelf.arr);
         };

2)MRC环境下:解决方式与上述基本一致,只不过将__weak关键字换成__block即可,这样的意思是告诉block:小子,不要在内部对self进行retain了!

19.id数据类型与静态类型

  • 虽然说id数据类型可以存储任何类型的对象,但是不要养成滥用这种通用类型
  • 如没有使用到多态尽量使用静态类型
  • 静态类型可以更早的发现错误(在编译阶段而不是运行阶段)
  • 静态类型能够提高程序的可读性
  • 使用动态类型前最好判断其真实类型
  • 动态类型判断类型
  • - (BOOL)isKindOfClass:classObj 判断实例对象是否是这个类或者这个类的子类的实例

20.分类(category)和类扩展(extension)

  • 分类中只能添加“方法”,不能增加成员变量。
  • 分类中可以访问原来类中的成员变量,但是只能访问@protect和@public形式的变量。如果想要访问本类中的私有变量,分类和子类一样,只能通过方法来访问。
  • 虽说category中无法直接添加属性,但是我们在Category中可以利用运行时添加属性:
- (void)setName:(NSString *)name
{
    objc_setAssociatedObject(self,
                             "name",
                             name,
                             OBJC_ASSOCIATION_COPY);
}

- (NSString*)name
{
    NSString *nameObject = objc_getAssociatedObject(self, "name");
    return nameObject;
}
  • 分类的执行优先级

    • 在本类和分类有相同的方法时,优先调用分类的方法再调用本类的方法。
    • 如果有两个分类,他们都实现了相同的方法,如何判断谁先执行?分类执行顺序可以通过targets,Build Phases,Complie Source进行调节,注意执行顺序是从上到下的。(只有两个相同方法名的分类)
  • 分类(category)和类扩展(extension)的关系

    • 类扩展(extension)是category的一个特例,有时候也被称为匿名分类。他的作用是为一个类添加一些私有的成员变量和方法。
    • 类扩展能写点啥?和分类不同,类扩展即可以声明成员变量又可以声明方法。

21.协议

协议中能够声明方法,以及属性。然后问题就来了,不是不能定义成员变量的吗?

对,的确不能定义成员变量,但是属性是什么?属性包含了三个东西:成员变量、setter方法、getter方法。在类中定义的属性,当然三者都有,然而协议中定义的属性只有获取和设置方法,没有成员变量,这就要求该协议的遵守者必须自己写出setter和getter方法的实现。但是有一种情况是不需要的,那就是遵守者本来就有这个属性,此时系统会为这个属性自动生成设置获取方法,既然已经实现了,那么遵守者就没必要去实现协议中的这个属性了。

尽管可以实现“伪属性”,但是,我们还是应该尽量把属性定义在主接口中,而不应该定义在协议中。

22.断言

- (void)printMyName:(NSString *)myName  
{  
    NSAssert(myName != nil, @"名字不能为空!");  
    NSLog(@"My name is %@.",myName);  
} 

当传给函数的参数(myName)为空时,断言将被执行,程序Crash,并打印出断言中的描述信息。本例中,在控制台打印出了如下的日志:

NSAssert[1268:a0b] *** Assertion failure in -[ViewController printMyName:]  
NSAssert/NSAssert/ViewController.m:38
2013-11-21 13:56:01.927 NSAssert[1268:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '名字不能为空!'

开发者没有必要在应用程序的每个版本中都进行断言检查,这是因为大多数项目都是有两个版本:Debug版和Release版。在Debug版中,开发者希望所有的断言都检查到,而在Release版中,往往都是禁用断言检查的。设置Release版本中禁用断言的方法如下:
在Build Settings菜单,找到Preprocessor Macros项,Preprocessor Macros项下面有一个选择,用于程序生成配置:Debug版和Release版。选择 Release项,设置NS_BLOCK_ASSERTIONS,不进行断言检查。

23.dispatch_barrier_sync和dispatch_barrier_async

共同点:
1、等待在它前面插入队列的任务先执行完
2、等待他们自己的任务执行完再执行后面的任务

不同点:
1、dispatch_barrier_sync将自己的任务插入到队列的时候,需要等待自己的任务结束之后才会继续插入被写在它后面的任务,然后执行它们
2、dispatch_barrier_async将自己的任务插入到队列之后,不会等待自己的任务结束,它会继续把后面的任务插入到队列,然后等待自己的任务结束后才执行后面任务。

24.NSObject + (void)load

25.__attribute__

参考链接

26.__IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_OS_VERSION_MIN_REQUIRED

这些编译期常量, 对运行时的环境判断完全无效, 它告诉编译器用哪一段代码来进行编译, 那那段代码里, 你仍然可以写运行到目标机器里会崩溃的代码

怎么解决? 组合!

  1. 我先判断编译环境, 以避免低版本SDK不认识高版本SDK的api, 造成编译错误(片段1)
  2. 在高版本SDK的条件内, 自行开始判断SDK版本, 或responedToSelector都可以,来判断是否使用高版本的api
  3. 在低版本条件内, 直接用低版本的api

27. NSRunLoop

28. get 请求重定向

  • NSURLConnetion方法
    使用NSURLConnetion类的NSURLConnectionDataDelegate中的代理方法
(nullable NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(nullable NSURLResponse *)response
  • NSURLSession方法
(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request
 completionHandler:(void (^)(NSURLRequest * __nullable))

29.接口函数过期提醒

使用时xcode会提示‘showWithMaskType’ is deprecated:Use show and setDefaultMaskType: instead.

+ (void)showWithMaskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use show and setDefaultMaskType: instead.")));

30 +load,constructor,main的执行顺序

+ (void)load{
    NSLog(@"load");
}
__attribute__((constructor))
void  constr(){
    NSLog(@"before main");
}

输出结果如下:
2016-07-21 22:13:58.591 Study[14185:5421811] load
2016-07-21 22:13:58.592 Study[14185:5421811] before main
2016-07-21 22:13:58.592 Study[14185:5421811] main

31. NSURLProtocol

@interface CustomURLProtocol : NSURLProtocol
@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //注册protocol
    [NSURLProtocol registerClass:[CustomURLProtocol class]];
    return YES;
}

32. NSURLSessionConfiguration

33.FOUNDATION_EXPORT 与#define

34. Keychain

35. CoreText

36. NSUserDefaults

37. WindowLevel

  • windowLevel有以下三种:
    • UIWindowLevelNormal;// 0.000000
    • UIWindowLevelStatusBar;// 1000.000000
    • UIWindowLevelAlert;// 2000.000000

1)当Level层级相同的时候,只有第一个设置为KeyWindow的显示出来,后面同级的再设置KeyWindow也不会显示。
2)statusLevelWindow在alertLevelWindow之后调用makeKeyAndVisible,仍然只是显示在alertLevelWindow的下方。这说明UIWindow在显示的时候是不管KeyWindow是谁,都是Level优先的,即Level最高的始终显示在最前面。

38.@synchronized

39.UIView setFrame方法

40.UIView的生命周期

41.delegate 作为属性需要使用weak

delegate作为属性需要是weak?
防止retain cycle循环引用...

比如tableview....UIViewCotroller通过self.view addsubview.已经指向tableview了......所以tableview.delegate = self 和tableview.datasource又指向了viewcontroller,如果此时delegate是strong,就会发生循环引用无法释放,所以这里应该是weak.....

42.readonly

43.__unsafe_unretained

44.UIScrollView下沉64像素

在ViewController中
self.edgesForExtendedLayout = UIRectEdgeNone;

self.automaticallyAdjustsScrollViewInsets = NO;

45.bounds与frame的区别

区别

46.获取字符串宽度

[self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}].width]

47.约束

mas_makeConstraints && mas_remakeConstraints && mas_updateConstraints

48.谓词(NSPredicate)

49.ViewController 和 xib关联

1、新建xxViewController 和 xib(xib 文件名与vc相同) ,并且设置xib 的 file’s owner 为xxViewController,
2、Outlets中的view 跟xib中的view做关联,如果没有这一步会报“loaded the "xxxView" nib but the view outlet was not set.”

第一种方法:
CustomViewController* customViewController = [[CustomViewController alloc] initWithNibName:nil bundle:nil];
你可以看现第一个传数是nil, 对没错,传nil也是可以的。因为如果系统发现是nil的话,会在工程的bundle里找与CustomViewController同名的xib文件,因为模版生成的正好名字相同,所以能够正确加载xib文件。
第二种方法:
CustomViewController* customViewController = [[CustomViewController alloc] init];
在这儿我们只是简单的初始化,也能正解加载相应的xib文件,因为他们名字是相同的。
如果xib的名了与类的名字不同呢?
如果不同那么我们就不能用上面的两种方法,必须显示指明xib的名字,如:
CustomViewController* customViewController = [[CustomViewController alloc] initWithNibName:"firstView" bundle:nil]
在这儿我们显示指明是firstView.xib这个文件。

50.枚举

NS_ENUM定义通用枚举,NS_ENUM定义的枚举不能几个枚举项同时存在,只能选择其中一项,

typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
    SDWebImageDownloaderFIFOExecutionOrder,
    SDWebImageDownloaderLIFOExecutionOrder
};

NS_OPTIONS定义位移枚举

typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
    SDWebImageDownloaderLowPriority = 1 << 0,
    SDWebImageDownloaderProgressiveDownload = 1 << 1,
    SDWebImageDownloaderUseNSURLCache = 1 << 2,
    SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
};

位移枚举即是在你需要的地方可以同时存在多个枚举值如这样:

SDWebImageDownloaderOptions opt = SDWebImageDownloaderLowPriority | SDWebImageDownloaderIgnoreCachedResponse;

判断的时候是这样

if (options & SDWebImageDownloaderUseNSURLCache){}

51.多线程中的数据同步

  • dispatch_semaphore
    GCD中信号量是dispatch_semaphore_t类型,支持信号通知和信号等待。每当发送一个信号通知,则信号量+1;每当发送一个等待信号时信号量-1,;如果信号量为0则信号会处于等待状态,直到信号量大于0开始执行。根据这个原理我们可以初始化一个信号量变量,默认信号量设置为1,每当有线程进入“加锁代码”之后就调用信号等待命令(此时信号量为0)开始等待,此时其他线程无法进入,执行完后发送信号通知(此时信号量为1),其他线程开始进入执行,如此一来就达到了线程同步目的。

  • @synchronized

  • NSLock

52. initialize load

+(void)load 在程序运行后立即执行
+(void)initialize 在类的方法第一次被调时执行

53.__block与__weak区别

54. performSelector调用和直接调用区别

  • performSelector是运行时系统负责去找方法的,在编译时候不做任何校验;如果直接调用编译是会自动校验。如果方法不存在,那么直接调用 在编译时候就能够发现(借助Xcode可以写完就发现),但是使用performSelector的话一定是在运行时候才能发现(此时程序崩溃);Cocoa支持在运行时向某个类添加方法,即方法编译时不存在,但是运行时候存在,这时候必然需要使用performSelector去调用。所以有时候如果使用了performSelector,为了程序的健壮性,会使用检查方法

  • 直接调用方法时候,一定要在头文件中声明该方法的使用,也要将头文件import进来。而使用performSelector时候, 可以不用import头文件包含方法的对象,直接用performSelector调用即可。

55.@autoreleasepool

当需要在程序中创建大量的临时变量时(大量也可指数量多,不确定,比如从数据库中读取数据时),很容易使内存产生峰值又回到内存低谷,这样对程序的性能会产生很大影响,而使用自动释放池后,峰值明显有所下降。
官方提出的解决方案是,在大量产生局部变量的位置用autoreleasepool代码块进行包装。比如for循环中要执行的语句,这样每次for循环结束后就会及时收回临时变量占用的内存空间。

for (int i = 0; i < 10e6; ++i) {
        @autoreleasepool {
        NSString *str = [NSString stringWithFormat:@"hi + %d", i];
        [collection addObject:str];
        }
    }

56.加载图片的两种方式

-imageNamed: 是读取到内存后会缓存下来,下次再读取时直接从缓存中获取,因此访问效率要比较高。对于图片资源比较小,使用比较频繁的图片,通常会选择使用此种方式来加载。当然,若不需要考虑性能时,直接使用此种方式也是可以的。
-initWithContentsOfFile: 当图片资源比较大,或者图片资源只使用一次就不再使用了,那么使用此种方式是最佳方式。当应用程序需要加载一张比较大的图片并且是一次性使用的,那么是没有必要去缓存这个图片的,用-imageWithContentsOfFile:是最为经济的方式,这样不会因为UIImage元素较多情况下,CPU会被逐个分散在不必要的缓存上而浪费过多CPU时间。另外,当我们的图片不是PNG图片时,我们通常会选择此种方式来加载。
SDWebImageDecoder引发的思考

57.NSData

58.NSCoding

59.属性修饰符

  • nullable
  • @property(nonatomic,getter=isOn) BOOL on;

60.导航栏遮挡view问题

if (kCurrentFloatDevice > 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeNone;
    }

61.NSException

62.NSError

63.方法中的数据传递和值传递

64. NSSortDescriptor

65. NSIndexSet

66. edgesForExtendedLayout

edgesForExtendedLayout浅淡,
edgesForExtendedLayout

相关文章

网友评论

      本文标题:一些知识点

      本文链接:https://www.haomeiwen.com/subject/xfzaqxtx.html