零散知识点记录,总有你需要的,持续更新
1、监听导航栏的frame 和 屏幕旋转起冲突,会崩溃
// 监听导航栏的frame
[self.navigationController.navigationBar addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
NSNumber *num = change[@"new"];
NSLog(@"-----------------------------num = %@",num);
CGRect rect = num.CGRectValue;
self.navBar.frame = rect;
}
- (void)dealloc{
[self.navigationController.navigationBar removeObserver:self forKeyPath:@"frame"];
}
/**
* @author 孔凡列, 16-09-21 08:09:06
*
* 横屏
*/
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
2、appDelegate 里面创建UIWindow的时候,需要指定window的frame,不然iOS8 的window的宽高会为0,但是iOS8以上就不会出现问题
self.window = [[UIWindow alloc] init];// 这样不行
self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0,0,SCREEN_WIDTH,SCREEN_HEIGHT)];// 这样就不会出现适配问题
3、AVAudioPlayer播放声音的时候,设置volume 为 1.0 后还是超级小声,超过1.0就会失真.添加一句代码可完美解决
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
4、监听横竖屏旋转,系统通知
UIDeviceOrientationDidChangeNotification
5、swift NSObject 的方法都不适用了,很多都是struct 不是 class
String 是struct 属于 Any 不是 AnyObject,所以iskind 不能用,用is 判断
6、iOS KVO监听数组元素个数变化(数组地址改变、插入、删除、替换)
- 需要 用
mutableArrayValueForKey
获取到的可变数组(网上说控制器的数组没办法监听,其实可以的,只是一定要用mutableArrayValueForKey
) - 还有一个注意点:分类中的数组是没办法监听到的,其他都可以
7、iOS 系统字体
[UIFont systemFontSize];// 系统默认字体大小 14
[UIFont smallSystemFontSize];// 小系统字体大小 12
[UIFont labelFontSize];// 系统label字体大小 17
[UIFont buttonFontSize];// 系统button字体大小 18
8、typeof(self) strongSelf = weakSelf; 的使用解答地址
总结
1、 在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。
2 、如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。此时self不会被释放,当block执行完后,会自动释放该strongSelf
9、layoutSubviews 什么时候调用?drawRect 什么时候调用?
-
视图的内容需要重绘时可以调用
setNeedsDisplay
方法,该方法会设置该视图的displayIfNeeded
变量为 YES ,NSRunLoop 在下一次循环检中测到该值为 YES 则会自动调用drawRect
进行重绘。 -
视图的内容没有变化,但在父视图中位置变化了可以调用
setNeedsLayout
,该方法会设置该视图的layoutIfNeeded
变量为YES,NSRunLoop 在下一次循环检中测到该值为 YES 则会自动调用layoutSubViews
进行重绘。
10、AFN3.0 支持ipv6,代码配置
HTTPS AFN 配置.png11、取状态栏判断网络状态
注意:飞行模式和关闭移动网络都拿不到dataNetworkType;1 - 2G; 2 - 3G; 3 - 4G; 5 - WIFI
BOOL flag = NO;
UIApplication *app = [UIApplication sharedApplication];
NSArray *children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
int netType = 0;
//获取到网络返回码
for (id child in children) {
NSLog(@"child = %@",NSStringFromClass([child class]));
if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
//获取到状态栏,飞行模式和关闭移动网络都拿不到dataNetworkType;1 - 2G; 2 - 3G; 3 - 4G; 5 - WIFI
netType = [[child valueForKeyPath:@"dataNetworkType"] intValue];
switch (netType) {
case 0:
flag = NO;
//无网模式
break;
default:
flag = YES;
break;
}
}
}
12、label 文字实现竖直排布
- 只需要设置
numberOfLines = 0
然后再调用sizeToFit
13、本地搭建IPv6环境测试你的APP(OS X 10.11 新加的功能)
Paste_Image.png打开系统偏好设置-按住
option
- 点击共享-创建NAT64
14、给 按钮 的imageView添加动画组
注意不能设置按钮的
backgroundImage
否则没动画效果
[playBtn setImage:[UIImage imageNamed:@"voice_button_01"] forState:UIControlStateNormal];
//设置动画图片的资源
playBtn.imageView.animationImages = self.animateBtnArrM;
//设置动画的持续时间
playBtn.imageView.animationDuration = 1.5;
//设置动画的执行次数
playBtn.imageView.animationRepeatCount = MAXFLOAT;
//开始动画
[playBtn.imageView startAnimating];
15、使用SDWebImage 加载 gif图片 url ,不能压缩,否则无法正常显示
加载GIF 可以 用webView 加载,UIWebView 有缓存,WKWebView 在 iOS 9 之后才有情况缓存的接口
16、滚动视图(UIScrollView 、UITableView、UIWebView、WKWebView、UICollectionView)界面点击事件,添加点击手势需要实现其中一个代理方法,才有点击效果
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
17、cocoapod search 不到所需的库
-
rm ~/Library/Caches/CocoaPods/search_index.json
执行完重新 search 就行
18、设置UITextField 水印居中
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 200, 200, 30)];
textField.borderStyle = UITextBorderStyleLine;
textField.placeholder = @"hello world";
UILabel *label = [textField valueForKey:@"_placeholderLabel"];
label.textAlignment = NSTextAlignmentCenter;
[textField setValue:label forKey:@"_placeholderLabel"];
[self.view addSubview:textField];
19、优雅地隐藏显示导航栏
- 遵守协议
<UINavigationControllerDelegate>
- 设置代理
self.navigationController.delegate = self;
- 重写方法
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
BOOL isVC = [viewController isKindOfClass:[self class]];
[self.navigationController setNavigationBarHidden:isVC animated:YES];
}
20、OC 的 指针,swift 的表示方法:
static const void* mainQueueKey = @"mainQueue";
static void* mainQueueContext = @"mainQueue";
private let mainQueueKey = UnsafeMutablePointer<Void>.alloc(1)
private let mainQueueValue = UnsafeMutablePointer<Void>.alloc(1)
21、swift 实现KVO以及提供给OC调用
- 需要使用@dynamic 和 @objc使用,默认如果使用@dynamic swift会隐式添加@objc
22、swift 使用runtime
- 如果是纯swift类,要使用runtime需要加上@dynamic,如果是直接或者间接继承NSObject(这个还是动态执行的),就可以直接使用runtime
23、宏定义的 attribute((visibility ("default"))) 作用
-
visibility属性是设置将本项目的函数作为库使用时的可见性。g++编译时, 加入-fvisibility=hidden参数, 会将所有默认public属性设为hidden, 导致库外文件不可见
-
如果设置了attribute((visibility ("default")))的函数, 其public属性仍能对外可见, 而不是hidden。可见编译指令 -fvisibility是对所有属性符号进行处理, 而attribute((visibility ("default")))是对特定函数可见性进行设置, 避免冲突。
原文地址
24、ARC 下使用 autoreleasepool
- 如果你创建太多的临时对象在你的代码中,你会注意到你的内存用量会增加直到对象被释放掉。问题是内存只有在UIKit排空(drains)自动释放池的时候才能被释放,这意味着内存被占用的时间超过了需要。好消息是你可以在你的@autoreleasepool段中创建临时对象来避免上述情况
NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
@autoreleasepool {
NSError *error;
NSString *fileContents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
/* Process the string, creating and autoreleasing more objects. */
}}
25、监听横竖屏切换
- 横竖屏切换的时候,系统会响应一些函数,其中
viewWillLayoutSubviews
和viewDidLayoutSubviews
。
26、并发 和 并行的区别
-
并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。
-
并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
区别:并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。
例子:
1).并发 一个送外卖的A需要把两份外卖分别送到两个客户B和C手里。 A必须先送完B外卖才能接着送C的。这就是并发
2).并行 客户C 分别从饿了么和美团订了一共两份外卖。那么外卖员A和外卖员B需要把外卖一同送到客户C手里。 这就是并行
27、 使用Instrument 的time profiler 调试
- 默认是不会显示方法名,需要项目中开启
Build Settings
->Build Options
->Debug
->DWARF with dSYM File
28、设置collectionView header 悬浮
- 设置 shouldInvalidateLayoutForBoundsChange属性为 YES就好