iOS 日常记录笔记

一,获取导航栏相关属性

  1. 获取包含导航栏的高度:
    CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
    CGRect rectNav = self.navigationController.navigationBar.frame;
    CGFloat maxY = rectStatus.size.height+rectNav.size.height;

二,字符串相关

  1. 截取,判断
 NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
 //1. 根据某个字符串截取成多个子串
 NSArray *subA = [msg componentsSeparatedByString:@"hosten_lym"];
 //2. 判断是否包含某个字符串
  NSRange range1 = [msg rangeOfString:@"hosten_lym"];
  if (range1.location != NSNotFound) {
      NSLog(@"%@",msg);
  }
  //3. 替换指定的字符串
  subS = [subS stringByReplacingOccurrencesOfString:@"str" withString:@"reStr"];

三, 关于可变数值或字典的一些事情

1,不可变使用 copy 属性防止数组被其他对象修改,可变必须使用 strong 或者 retain ,原因如下:

@property(nonatomic, copy) NSMutableArray *remoteVideoMutArray;
 _remoteVideoMutArray = [[NSMutableArray alloc] init];
[self.remoteVideoMutArray addObject:dic];

这样做会导致一个崩溃,如图:
这里写图片描述
实际上使用copy属性后;这里实际上已经转为不可变的数组,再对其赋值,就会导致上述错误,原理如下:

@property(nonatomic, copy) NSMutableArray *remoteVideoMutArray;
 _remoteVideoMutArray = [[[NSMutableArray alloc] init] copy];
[self.remoteVideoMutArray addObject:dic];

因此,可变必须使用 strong 或者 retain ;
20210411更新:这里其实是深copy和潜copy的问题
    浅拷贝是指针copy会影响引用计数,不开辟内存空间,深copy是数据copy不会影响引用计数,开辟内存空间;

对象类型copy方式结果copy类型
mutable对象copy不可变浅拷贝
mutable对象mutablecopy可变深拷贝
immutable对象copy不可变浅拷贝
immutable对象mutablecopy可变深拷贝

即:copy 之后的返回的对象都是不可变,mutablecopy之后返回的对象都是可变

四.关于控制器那些事

  1. 获取window下rootVC
- (UIViewController *)getCurrentVC
{
    UIViewController *result = nil;
    UIWindow * window = ((AppDelegate*)SYS_DELEGATE).window;
    if (window.windowLevel != UIWindowLevelNormal)
    {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(UIWindow * tmpWin in windows)
        {
            if (tmpWin.windowLevel == UIWindowLevelNormal)
            {
                window = tmpWin;
                break;
            }
        }
    }
    
    UIView *frontView = [[window subviews] objectAtIndex:0];
    id nextResponder = [frontView nextResponder];
    
    if ([nextResponder isKindOfClass:[UIViewController class]])
        result = nextResponder;
    else
        result = window.rootViewController;
    
    return result;
}

  1. 根据rootVC获取最顶层的控制器:
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController

{
    
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        
        UITabBarController *tabBarController = (UITabBarController *)rootViewController;
        
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
        
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
        
    } else if (rootViewController.presentedViewController) {
        
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        
        return [self topViewControllerWithRootViewController:presentedViewController];
        
    } else {
        
        return rootViewController;
        
    }
    
}

3:多个控制器(父子控制器)
父子控制器

  • 一般可以直接在一个控制器中直接把其他控制器的view添加进去,但是这样会导致很多问题;
[self.view addSubview:vc.view];
  • 父子控制器
- (void) showView{//显示子控制器的view
  // 获取之前控制器的view
    UIView *firstView;
    if (self.contentView.subviews.count) {
       firstView  = self.contentView.subviews[0];  
    }
    // 显示子控制器
    UIViewController *vc = self.childViewControllers[sender.tag];
    vc.view.frame = self.contentView.bounds;
    [self.contentView addSubview:vc.view];
    // 移除之前控制器的view
    [firstView removeFromSuperview];
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 1.添加子控制器
    [self setUpCreateAllChildViewController];
    // 2.设置按钮标题
    [self setUpButtonTitle];
}
- (void)setUpButtonTitle
{
    NSUInteger count = self.titleView.subviews.count;
    // 3
    // 0 1 2
    for (int i = 0; i < count; i++) {
        
        UIButton *btn = self.titleView.subviews[i];
        UIViewController *vc = self.childViewControllers[i];
        //将控制器的标题设置给按钮
        [btn setTitle:vc.title forState:UIControlStateNormal];
    }
}
// 添加子控制器
- (void)setUpCreateAllChildViewController
{
    // 社会
    test1ViewController *societyVc = [[test1ViewController alloc] init];
    societyVc.title = @"测试1";
    [self addChildViewController:societyVc];
    
    // 头条
    test2ViewController *topLine = [[test2ViewController alloc] init];
    topLine.title = @"头条";
    [self addChildViewController:topLine];
    
    // 热点
    test3ViewController *hotVc = [[test3ViewController alloc] init];
    hotVc.title = @"热点";
    [self addChildViewController:hotVc];
}

优点:

1. 父子控制中的自控制器可以使用导航控制器的push方法

五,应用后台模式(录音):

1:info.plist配置:
这里写图片描述
2:audio设置:

//设置设备允许蓝牙
- (BOOL)prepareAudioSession {
    
    // deactivate session
    BOOL success = [[AVAudioSession sharedInstance] setActive:NO error: nil];
    if (!success) {
        NSLog(@"deactivationError");
    }
    // set audio session category AVAudioSessionCategoryPlayAndRecord options AVAudioSessionCategoryOptionAllowBluetooth
    success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
    if (!success) {
        NSLog(@"setCategoryError");
    }
    
    // activate audio session
    success = [[AVAudioSession sharedInstance] setActive:YES error: nil];
    if (!success) {
        NSLog(@"activationError");
    }
    return success;
}

3:设置后台点击状态栏跳转到应用

//应用支持远程事件
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];  

4:实现效果:
这里写图片描述

六,库的那些事

1:库体积太大
命令行执行:

strip -S -X RTCSDK.framework/RTCSDK

2: 查看库中所有符号表:

nm -a

七,环境配置

在mac下配置cocos2dx游戏引擎的android编译环境配置

1、打开terminal(终端)

2、cd ~ ( 进入当前用户的home目录)

3、open .bash_profile (打开.bash_profile文件)

4、直接更改弹出的.bash_profile文件内容

5、command + s 保存文件,然后关闭

6、在terminal(终端)中输入 source .bash_profile (使用刚才更新之后的内容)

八,关于dispatch_semaphore的使用

  1. 例子:
 // We want a synchronous request so that we know that we've left the room on
  // room server before we do any further work.
  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
  [NSURLConnection sendAsyncRequest:request
                  completionHandler:^(NSURLResponse *response, NSData *data, NSError *e) {
                    if (e) {
                      error = e;
                    }
                    dispatch_semaphore_signal(sem);
                  }];

  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

  1. 简述: 信号量的具体做法是:当信号计数大于0时,每条进来的线程使计数减1,直到变为0,变为0后其他的线程将进不来,处于等待状态;执行完任务的线程释放信号,使计数加1,如此循环下去。
`dispatch_samaphore_t dispatch_semaphore_create(long value)`
   传入的参数为long,输出一个dispatch_semaphore_t类型且值为value的信号量。   

long dispatch_semaphore_signal(dispatch_semaphore_tdsema)
  这个函数会使传入的信号量dsema的值加1
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
  这个函数会使传入的信号量dsema的值减1;

九,UITableView

1. storyboard 自定义cell高度

    //告诉tableView的真实高度是根据约束计算的
    _tableView.rowHeight = UITableViewAutomaticDimension;
    //设置估算高度
    _tableView.estimatedRowHeight = 50;

2. tableView编辑模式

//cell 添加多个按钮
-(NSArray<UITableViewRowAction*>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewRowAction *action = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        NSLog(@"=--------删除");
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewAutomaticDimension];
//        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
    }];
    UITableViewRowAction *visAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"关注" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
         NSLog(@"=--------关注");
        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
    }];
    visAction.backgroundColor = [UIColor blueColor];
    UITableViewRowAction *cancleaction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"取消" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
         NSLog(@"=--------关注");
    }];
    return @[action,visAction,cancleaction];
}

一些控制台命令

  1. 文件操作:
  • 查找文件中特定字符串
命令1:grep “测试字符串” log.txt
作用:从log.txt中找出“测试字符串”的数据
命令2:grep -n “测试字符串” log.txt
作用:从log.txt中找出“测试字符串”位置的数据,并在前面加上行号
命令3:grep (-n) Hello * (是否加上行号)
作用:从当前目录下的所有文件中找出出现过Hello的文件

一些开发便捷工具

  • Alfred 便携搜索
  • XtraFinder
  • iTerm2
  • Go2Shell

callKit 遇到的问题

  • 1.CXEndCallAction 结束报错(Domain = com.apple.CallKit.error.requesttransaction Code = 4)问题;
    CallKit对于每一个VoIP应用都应该只能有一个CXProviderCXCallController的实例对象;重复的实例化CXProvider,那么在后续的结束时候就会出现上述错误,因此对于callKit 使用一个单例的类来管理,同时用来确保只能有一个CXProviderCXCallController实例;使用下列方式来更新CXProviderConfiguration
     [self.callKitProvider setConfiguration:configuration];
    

XCode 12 显示某一行代码是谁修改的

下面的步骤都是基于sourcetree ,也就是XCode里已经加入了git账户等设置;然后根据下述流程就能显示每一行代码是谁修改的了;

  1. 点击下图右上角箭头所指的图标
    在这里插入图片描述
  2. 选中箭头所示选项
    在这里插入图片描述
  3. 然后就可以愉快的定位是谁修改了哪一行代码了,效果如下

在这里插入图片描述
4. 命令行git命令定位 方法:

  • 在文件所在的目录打开命令行输入
 git blame -L 150,300   文件名.m

‘-L’ 可选参数 表示 要查看的行数范围

  • 查看提交记录
git show comitid
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简简单单lym

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值