• [BS] 小知识点总结-02


    1.  dispatch_GCD 可让某操作延迟x秒执行

        //模拟网速慢,延迟3s返回数据(就会导致右侧数据和左侧标签不对应)

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            [[AFHTTPSessionManager manager] GET:@"http://api.budejie.com/api/api_open.php" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) { //AFN在子线程中发送HTTP请求,一旦获取responseObject值,就会来到success后面的block,该block属于mainThread主线程,以便刷新UI界面。

                NSArray *users = [WZRecommendUser mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];//字典数组转模型数组

            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

            }];

        }); 

    2. 内存警告的监听:

    2.1 AppDelgate.m中有这样的代理方法,可以监听整个app的内存警告

    - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {

          // try to clean up as much memory as possible. next step is to terminate app

    }

     2.2 ViewController.m中的didReceiveMemoryWarning也可以

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

    }

    3. 数组添加对象的2种方法

    [aArray addObjects: bArray]; //把b数组整体存入aArray[0]位置

    [aArray addObjectsFromAArray: bArray];//把b数组中每个元素存到a数组对应的位置

    4. OC中id类型的对象(如直接从数组取出的对象、或通过key从字典中取出的对象)不能使用点语法,但是可以采用方括号方法调用。

    5. 在数据模型中声明的NSMutableArray属性,必须懒加载重写get方法才能在另一个类中动态的添加对象。因为NSMutable**类型的变量,必须先初始化,然后才能使用。

    6.

    MJRefresh中的mj_header必须显性调用[self.tableView.mj_header beginRefreshing]; 才会显示并执行block,或者用户手指下拉时才显示并执行block。但header一旦显示,就必须显性调用[self.tableView.mj_header endRefreshing];才会隐藏。

    MJRefresh中的mj_footer默认是显示的,需要在tableView的数据源方法numberOfRowsInSection中设置是否隐藏【self.tableView.mj_footer.hidden = (model.count == 0); 】。只要tableView页面滚动到footer的位置,就会自动触发footer加载动画,并执行block中代码。footer加载动画启动后,也需要显性调用endRefreshing或者endRefreshingWithNoMoreData来停止加载动画。

    7.

    - (void)dealloc { //所有的AFN请求都使用self.sessionManager发送

        //控制器销毁或退出时,让sessionManager队列中所有的操作取消

        [self.sessionManager.operationQueue cancelAllOperations];

    }

    8. 在用户多次快速点击,连续发送请求时,如何只处理最后一次请求

        //1.参数
        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        params[@"a"] = @"list";
        params[@"c"] = @"subscribe";
        //全局的属性变量只保存最后一次网络请求数据
        self.paragsDict = params;
        
        //2.请求
        [self.sessionManager GET:@"http://api.budejie.com/api/api_open.php" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject)
        {
            //self.paragsDict中保存的是最后一次点击的请求参数,而parags是局部变量,parags存的是当时发请求的参数,如果不相等,说明这不是最后一次请求,不处理。只处理最后一次请求。
            if (self.paragsDict != params)  return;
                 
            //字典数组转模型数组
            //刷新右侧表格数据,调cellForRow方法
            [self.userTableView reloadData];
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //如果不相等,说明这不是最后一次请求,不处理。只处理最后一次请求。
            if (self.paragsDict != params)  return;
            [SVProgressHUD showErrorWithStatus:@"网络繁忙,右侧数据获取失败"];//会自动关闭
        }];

     9. NSData和NSArray相互转换:

        NSArray *arr1 = [[NSArray alloc]initWithObjects:@"0",@"5",nil];
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr1];
        NSArray *arr2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

    10. 固定自定义控件的长宽

      如果想让一个自定义的UI控件的尺寸(长宽)不能被改变,只需在该类.m中重写setFrame和setBounds方法,将frame和bounds修改为固定大小,然后调用super方法将设定好的frame和bounds传进去即可。

    11. 自定义键盘

      // 更换键盘(如表情键盘)

        UIView *keyboard = [[UIView alloc] init];

        keyboard.frame = CGRectMake(0, 0, 0, 100);

        keyboard.backgroundColor = [UIColor redColor];

        self.emailField.inputView = keyboard;

        // 设置键盘顶部的工具条;

        UIView *toolbar = [[UIView alloc] init];

        toolbar.frame = CGRectMake(0, 0, 0, 44);

        toolbar.backgroundColor = [UIColor blueColor];

        self.nameField.inputAccessoryView = toolbar;

    12. UITableViewWrapperView

      在iOS7以下系统,UITableViewCell.superview就是 UITableView,但在IOS7中,cell上面还多了一个 UITableViewWrapperView,所以需要 UITableViewCell.superview.superview获取UITableView 

    13. 让TabelViewCell左右留出空白间距,下方留出空白间距作为分割线

      12.1 设置cell的contentView的frame

      12.2 直接在conte

    14.打印当前app的info.plist文件

      NSLog(@"%@",[UIBundle mainBundle].infoDictionary);

    15. UIView有个属性@property(nonatomic, strong) UIColor *tintColor 用来设置鼠标颜色、渐变色、导航颜色等。例如设置UITextField聚焦时光标的颜色,就可以用:textField.tintColor = [UIColor redColor];光标被修改为红色。

    16. ios程序的编译、链接、打包、安装、执行

    程序开发好了Xcode会调用Mac系统的clang编译器会将程序员写的每个类.h/.m(源文件)进行编译,产生目标文件.o,然后将所有的目标文件+引用的框架文件,链接在一起,产生一个可执行的二进制文件.Mach-O,可执行程序文件.Mach-O包括BSS段、数据段代码段(也称文本段)。它们都是有编译器在程序运行前就分配好的。应用程序安装包,是使用Xcode的Organizer-Archives将可执行文件.Mach-O+资源文件(图片/声音/plist)、nib、第三方bundle全部打包成一个.app的压缩包,然后再打包成.ipa格式,发放给用户安装在手机上。(自己理解,可能有误)

    补充:

    Xcode 的默认编译器是 clang。本文中我们提到的编译器都表示 clang。clang 的功能是首先对 Objective-C 代码做分析检查,然后将其转换为低级的类汇编代码:LLVM Intermediate Representation(LLVM 中间表达码)。接着 LLVM 会执行相关指令将 LLVM IR 编译成目标平台上的本地字节码,这个过程的完成方式可以是即时编译 (Just-in-time),或在编译的时候完成。

    LLVM 指令的一个好处就是可以在支持 LLVM 的任意平台上生成和运行 LLVM 指令。例如,你写的一个 iOS app, 它可以自动的运行在两个完全不同的架构(Inter 和 ARM)上,LLVM 会根据不同的平台将 IR 码转换为对应的本地字节码。

     17. 所有的UIView都有一个- (void)layoutIfNeeded方法,可让View立即刷新状态(布局子视图)。使用UIAppearance设置导航按钮状态后,再修改导航按钮disable状态就不会奏效,此时需让[navigationBar layoutIfNeeded];

    Description: Lays out the subviews immediately. Use this method to force the layout of subviews before drawing. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root.

    18.

    在iOS开发中,经常要考虑系统的向下兼容,如果使用了低版本不存在的API ,则不能向下兼容,这时候如果想兼容低版本,就需要根据当前设备的版本进行不同的处理,在低版本中可能要牺牲一些新功能。判断iOS版本以便向下兼容代码通常写法:

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
    // iOS 8.0以上 code

    }
    else {
    // iOS 8.0以下 code
    }

    //可以定义一个宏来判断,以方便使用 

    #define  IOS_VERSION_5_OR_ABOVE   (([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)? (YES):(NO))

     

     

    //以下2个宏和使用的Xcode及Xcode的设定值有关。不能用来判定软件版本号。

    NSLog(@"MAX:%d",__IPHONE_OS_VERSION_MAX_ALLOWED);//MAX是Xcode中Develop Target能够设置的最大值,例如Xcode7.0最多能开发iOS9.0的软件

    NSLog(@"MIN:%d",__IPHONE_OS_VERSION_MIN_REQUIRED);//MIN宏就是Xcode中Develop Target当前设定的值

    2016-06-05 15:16:58.315 PlayMusicAndSound[3041:216356] MAX:90000

    2016-06-05 15:16:58.315 PlayMusicAndSound[3041:216356] MIN:80000

     

     

    //下面是ios内其他相关信息的判断方法
    获取进程信息和设备信息(包括设备类型,序列号,ios版本等)
    [[NSProcessInfo processInfo] globallyUniqueString],
    [[NSProcessInfo processInfo] hostName],
    [[NSProcessInfo processInfo] operatingSystemName],
    [[NSProcessInfo processInfo] operatingSystemVersionString],
    [[NSProcessInfo processInfo] physicalMemory],
    [[NSProcessInfo processInfo] processName]);
    ——————————————————————————————
    [UIDevice currentDevice].uniqueIdentifier,
    [UIDevice currentDevice].name,
    [UIDevice currentDevice].systemName,
    [UIDevice currentDevice].systemVersion,
    [UIDevice currentDevice].model,
    [UIDevice currentDevice].localizedModel,
    [UIDevice currentDevice].batteryLevel

    19.   AVAudioPlayer  AVPlayer的区别

       * AVAudioPlayer,该类带Audio,说明只能播放本地音乐。而且一个audioPlayer只能包含一个url,只能播放一个音频文件。

       * AVPlayer, 即是Audio Vedio Player, 既能播放本地的音频、视频,又能播放网上的音频、视频

    注意:正式开发过程中iOS项目名称一定不要有汉字或奇怪的符号,可能导致播放本地视频/音频时,URL出现莫名其妙的错误

    20. 因为block会默认对其中使用的对象进行强引用,Block里使用Block外面定义的局部变量,也需在局部变量前加上__block来保证局部变量在出了方法的{}作用域后不被销毁,等到block中代码执行完了才销毁。

    一般在控制器中使用多线程下载图片/文件等,如dispatch_async/sync函数,NSBlockOperation操作都会使用block,在这些Block中如果使用self控制器的属性,就可能构成循环引用。

    例如:self.queue = [[NSOperationQueue alloc]init];    [self.queue addOperation:operation];  

    operation = [NSBlockOperation blockOperationWithBlock:^{  NSData *data = [NSData dataWithContentsOfURL: modal.url];

    self.imagesDict[model.url] = [UIImage imageWithData: data];  }];

    以上代码: 控制器强引用operationQueue, operationQueue又强引用operation,operation中的block又使用控制器的imagesDict字典,block默认对使用的控制器self进行强引用,这样就会导致控制器self和operation互相强引用,形成循环引用。

    解决以上问题的方法是:在operation的Block外面定义一个控制器的若引用,在Block中使用该弱引用来调用控制器的imagesDict字典。

    __weak typeof(self)  vc = self;  //注意typeof(self)是获取类型的函数,相当于__weak UIViewController *  vc = self;

    operation = [NSBlockOperation blockOperationWithBlock:^{  NSData *data = [NSData dataWithContentsOfURL: modal.url];

    vc.imagesDict[model.url] = [UIImage imageWithData: data];  }];

    注意:如果只是block引用控制器,控制器没有对block进行强引用,则不需要使用弱引用的控制器。

    [UIView animateWithDuration: 1.0 animations:^{

            self.view.bounds = CGRectMake(0, 0, 200, 200);

        }]; //仅仅是block对控制器引用

    21.

    如果下载操作非常复杂,代码非常多,可以考虑将下载操作放在自定义operation,可以新建一个继承自NSOperation的子类WZOperation,以后使用WZOperation *opt = [[WZOperation alloc]init]; 创建操作,并且将它添加到队列[[NSOperationQueue alloc]init] addOperation: opt]; 这行代码就会立即调用WZOperation.m中重写的-(void)main{}方法中的代码。

    WZOperation.m代码的固定写法

    - (void)main {

      @autoreleasepool{ //在异步线程创建的autorelease对象无法添加到主线程的main()函数中的自动释放池。

        if (self.isCancel) return; //每做完一段耗时操作前后都要判断是否被取消。

          //写自定义的代码

        if (self.isCancel) return;

      }

    }

     

    ***注意:NSOperationQueue中有100个操作operaion, 如果下载到28个,还有2个线程正在下载,尚未完成,此时如果调用[queue cancelAllOperation]; 只会取消后面70个尚未开始下载的操作,对已经完成的和正在下载的操作没有任何影响。

    22.

    SDWebImage通过imageIO框架来播放gif(帧动画)。可以设置定期清理缓存。

    //应用程序代理可监控ios系统发来的内存警告,然后在分发给每个实现- (void)didReceiveMemoryWarning{}方法的控制器
    - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
        
        //SDWebImage中两个重要的单例:SDWebImageManager 和 SDImageCache
        
        [[SDWebImageManager sharedManager] cancelAll]; //取消所有操作(正在下载的不会取消)
        [[SDWebImageManager sharedManager].imageCache clearMemory]; //通过Manager拿到imageCache单例,清除内存
        
        [[SDImageCache sharedImageCache] clearMemory];//清除内存缓存
        [[SDImageCache sharedImageCache] clearDisk]; //清除硬盘缓存
        [[SDImageCache sharedImageCache] cleanDisk];//清理过期的缓存 (默认为7天)
        NSUInteger cacheBytes = [SDImageCache sharedImageCache].getSize; //获取硬盘上已缓存的字节B数
        
        //可通过SDImageCache的如下属性设置缓存天数
        /**
         * use memory cache [defaults to YES]
         */
        @property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
        
        /**
         * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
         */
        @property (assign, nonatomic) NSUInteger maxMemoryCost;
        
        /**
         * The maximum number of objects the cache should hold.
         */
        @property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
        
        /**
         * The maximum length of time to keep an image in the cache, in seconds
         */
        @property (assign, nonatomic) NSInteger maxCacheAge;
        
        /**
         * The maximum size of the cache, in bytes.
         */
        @property (assign, nonatomic) NSUInteger maxCacheSize;
    }

    23.

     

     

    iOS开发者交流群:180080550
  • 相关阅读:
    ORA-06530: 引用未初始化的组合 ;
    oracle 简单的sysTimeStamp类型转date 类型
    Luogu P3388 【模板】割点(割顶)
    Luogu P2048 [NOI2010]超级钢琴
    Luogu P2657 [SCOI2009]windy数
    QZEZ第一届“饭吉圆”杯程序设计竞赛
    Luogu P2286 [HNOI2004]宠物收养场
    在平衡树的海洋中畅游(一)——Treap
    Luogu P1129 [ZJOI2007]矩阵游戏
    LOJ #559. 「LibreOJ Round #9」ZQC 的迷宫
  • 原文地址:https://www.cnblogs.com/stevenwuzheng/p/5443744.html
Copyright © 2020-2023  润新知