iOS知识集锦(持续更新)

2016-10-21  本文已影响55人  神采飞扬_2015

ruby.taobao.org 停止更新了,使用 cocoapods 的童鞋,更新到 ruby china 的源

$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -lhttps://gems.ruby-china.org # 确保只有 gems.ruby-china.org
$ gem sources -l 
*** CURRENT SOURCES ***
https://gems.ruby-china.org
# 请确保只有 gems.ruby-china.org
$ gem install rails

$ gem install rails时出现这样的错误:

yitudevdeiMac:~ yitudev$ gem install rails
Building native extensions.  This could take a while...
ERROR:  While executing gem ... (Errno::EACCES)
    Permission denied @ dir_s_mkdir - /usr/local/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0/nokogiri-1.6.8.1
yitudevdeiMac:~ yitudev$ gem install rails
Building native extensions.  This could take a while...

进行操作:

yitudevdeiMac:~ yitudev$ sudo gem install cocoapods-core 

再$ gem install rails。当pod setup 进入Setting up CocoaPods master repo 等待的时候表示正在下载了,此时你可通过新开一个终端窗口,输入"cd ~/.cocoapods/"命令行跳到cocoapods文件夹内,执行"du -sh *"查看正在下载的文件夹的大小。
CocoaPods 的简单快速安装方法(Setting up CocoaPods master repo 卡着不动,是因为淘宝镜像已经不能用了)

pod install --verbose --no-repo-update
pod update --verbose --no-repo-update

NULL、nil、Nil、NSNull区别

标志 含义
NULL (void *)0 C 指针的字面空值
nil (id)0 Objective-C 对象的字面空值
Nil (Class)0 Objective-C 类的字面空值
NSNull [NSNull null] 用来表示空值的 Objective-C 对象
int *pointerToInt = NULL;
char *pointerToChar = NULL;
struct TreeNode *rootNode = NULL;
NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;
if (anotherObject == nil) 
Class someClass = Nil;
Class anotherClass = [NSString class];
// 当 NSArray 里遇到 nil 时,就说明这个数组对象的元素截止了,即 NSArray 只关注 nil 之前的对象,nil 之后的对象会被抛弃。
NSArray *array = [NSArray arrayWithObjects:@"one", @"two", nil];

// 错误的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@"someKey"];

// 正确的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"someKey"];

取消延迟执行函数

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;  
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;  
// 取消某一个延时调用请求
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument; 
// 取消performSelector的所有被延迟执行的方法 
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget; 
// 创建定时器的time-类方法,需要手动fire开启定时器,将执行方法封装到NSInvocation中
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
// 创建定时器的time-类方法,需要手动fire开启定时器
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
// 创建定时器的scheduled-类方法,不需要手动fire开启定时器,将执行方法封装到NSInvocation中
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
// 创建定时器的scheduled-类方法,不需要手动fire开启定时器
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
// 创建定时器的实例方法,会在指定时间开启定时器
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;
// 开启定时器
- (void)fire;
// 使定时器失效,将定时器从循环池移除掉
- (void)invalidate;

self.timer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(prtintMyWords:) userInfo:@{@"words":@"hello world"} repeats:NO];
[self.timer invalidate];
// 创建延迟时间,从当前时间开始,3秒后执行。 3秒需要转化为纳秒,因为该函数是以纳秒为基础进行的
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 3.0*NSEC_PER_SEC);
// 执行延迟函数
dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   [self printString:@"hello world"];
});

版本号如何控制

GNU 风格的版本号管理策略:一般的版本号划分为如下3个部分——“主版本号 . 子版本号 . 修正版本号”,简单直观清晰。
1、项目初版本时,版本号可以为 0.1 或 0.1.0, 也可以为 1.0 或 1.0.0 (例如: 1.0.0 )
2、当项目在进行了局部修改或 bug 修正时,主版本号和子版本号都不变,修正版本号加 1 (例如: 1.0.1 )
3、当项目在原有的基础上增加了部分功能时,主版本号不变,子版本号加 1,修正版本号复位为 0 (例如: 1.1.0 )
4、当项目在进行了重大修改或局部修正累积较多,而导致项目整体发生全局变化时,主版本号加 1 (例如: 2.0.0 )
5、另外,编译版本号一般是编译器在编译过程中自动生成的,我们只定义其格式,并不进行人为控制。

直接调用方法和使用performSelector调用的区别

1、两种方式执行的效果其实和发送消息是等价的。
2、performSelector允许发送未在运行时确定的消息;也就是说,只要这个消息能够被转发到正确的接收者,能够被最后的接收者识别,都是可以正确运行的。否则,就会在运行时报错“unrecognized selector sent to instance”。如果没有实现该方法,只能在运行时才会报错,编译阶段发现不了。
3、Obejct-C的动态特性是允许在运行时向某个类添加方法的,这个时候就一定需要使用performSelector。那么为了避免运行时出现错误,在使用performSelector之前一定要使用如下的检查方法来进行判断。我们一般都忽略的用该方法进行判断。

- (BOOL)respondsToSelector:(SEL)aSelector;

#pragma 处理防止编译器警告

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-相关命令" 
// 你自己的代码
#pragma clang diagnostic pop
#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wdeprecated-declarations" 
[TestFlight setDeviceIdentifier:[[UIDevice currentDevice] uniqueIdentifier]]; 
#pragma clang diagnostic pop

2、不兼容指针类型

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"  
// 
#pragma clang diagnostic pop

3、循环引用

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Warc-retain-cycles"  
  self.completionBlock = ^ {
     ... 
  }; 
#pragma clang diagnostic pop

4、未使用变量

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wunused-variable"  
int a; 
#pragma clang diagnostic pop

5、参数不固定的情况:以DKNightVersion为例

DKImagePicker DKImagePickerWithNames(NSString *normalName, ...) {
    NSArray<DKThemeVersion *> *themes = [DKColorTable sharedColorTable].themes;
    NSMutableArray<NSString *> *names = [[NSMutableArray alloc] initWithCapacity:themes.count];
    [names addObject:normalName];
    NSUInteger num_args = themes.count - 1;
    va_list names_list;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wvarargs"
    va_start(names_list, num_args);
#pragma clang diagnostic pop
    for (NSUInteger i = 0; i < num_args; i++) {
        NSString *name = va_arg(names_list, NSString *);
        [names addObject:name];
    }
    va_end(names_list);

    return [DKImage pickerWithNames:names];
}

va_arg(va_list ap, type),参数ap应该首先被宏va_start 或 va_copy初始化,但又必须在被宏va_end调用之前使用。每次调用va_arg都会改变ap值使得后续的参数值能被依次添加。参数type应该是一个类型名,并且用type*能够得到该类型的指针类型。如果type为空,或者type和实际参数不匹配, 那么除了以下两种情况,这个宏的行为是未定义的。
用法:
(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
(2)然后用VA_START宏初始化刚定义的VA_LIST变量;
(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
(4)最后用VA_END宏结束可变参数的获取。

在对象内部尽量直接访问实例变量

消息传递、转发机制

isMemberOfClass:与isKindOfClass:区别

上一篇 下一篇

猜你喜欢

热点阅读