iOS 零散知识点记录

总会有你需要的

Posted by gitKong on February 23, 2017

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、iOS8 的window的宽高会为0

  • 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播放超级小声或失真

  • AVAudioPlayer播放声音的时候,设置volume 为 1.0 后还是超级小声,超过1.0就会失真.添加一句代码可完美解决
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];

4、监听横竖屏旋转,系统通知

UIDeviceOrientationDidChangeNotification

5、swift 的 NSObject

  • 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、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 配置.png

11、取状态栏判断网络状态

注意:飞行模式和关闭移动网络都拿不到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环境测试

(OS X 10.11 新加的功能)

打开系统偏好设置-按住 option - 点击共享-创建NAT64

Paste_Image.png

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 的问题

  • 不能压缩,否则无法正常显示

加载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”)))是对特定函数可见性进行设置, 避免冲突。 原文地址