zoukankan      html  css  js  c++  java
  • 懒加载(延迟加载)之后,在使用数据过程中容易出现的bug

    在UI中,使用懒加载,也就是延迟加载来加载数据的时候,总是会面临几个问题?

    如:1. >为什么先创建NSArray属性?

        2. >为什么重写NSArray的get方法?

        3.>为什么要判断是否为空?

        4.>为什么下方代码"//1"这里不用NSString stringWithFormat: 而"//2"这里要使用? 

        5.>同时"//2"这里为什么使用的是%ld 来作为占位符?

    这些问题不搞懂,懒加载就很难通透,  代码如下:

     1 #import "ViewController.h"
     2 
     3 @interface ViewController ()
     4 //先创建一个属性  (因为需要加载由字典组成的这个数组(也就是plist文件),所以需要先定义数组属性来接收和表示,)
     5 @property (nonatomic, strong) NSArray *pictures;
     6 @end
     7 
     8 @implementation ViewController
     9 
    10 //.重写pictures属性的get方法, 在该属性的get方法中读取images.plist文件中的数据, 并将数据设置给pictures属性
    11 // 这种加载数据的方式就叫做"懒加载"
    12 - (NSArray *)pictures {
    13     if (_pictures == nil) { 
    14         // 读取plist文件并加载数据
    15         // 1. 获取images.plist文件的完整的路径   
    16         NSString *path = [[NSBundle mainBundle] pathForResource:@"images.plist" ofType:nil];    
    17         // 2. 根据plist文件的路径, 加载plist文件,再赋值给数组
    18         _pictures = [NSArray arrayWithContentsOfFile:path];
    19     }
    20     return _pictures;
    21 }
    22 @end
    23 
    24  // 封装一个修改界面控件数据的方法
    25 - (void)loadData {
    26     // 2. 取出当前self.pictures中的对应的数据
    27    NSDictionary *dict = self.pictures[self.index];
    28     
    29     // 3. 把数据设置到界面中对应的控件上
    30    self.lblTitle.text = dict[@"desc"];  // 1
    31    self.imgViewIcon.image = [UIImage imageNamed:dict[@"icon"]];
    32    self.lblIndex.text = [NSString stringWithFormat:@"%d / %ld", self.index + 1, self.pictures.count];   //2
    33     
    34     
    35     // 设置"上一张"按钮 和 "下一张" 按钮的状态
    36    self.btnPrevious.enabled = (self.index <= 0) ? NO : YES;
    37    self.btnNext.enabled = (self.index >= self.pictures.count - 1) ? NO : YES;
    38 }

    原因及bug解析:

      1.>为什么先创建NSArray属性?
    因为需要加载由字典组成的这个数组(也就是plist文件),所以需要先定义数组属性来接收和表示,
      2. >为什么重写NSArray的get方法?
        因为在程序运行的时候,当需要读取这个数组的数据时,此时NSArray这个数组里面是空的,空的数组是没法满足我们的需求的,所以,我们这里就拦截这个get方法,重写它,将需要的数据加载进去,这样下面运行的时候,就会有我们需要的数据了
      3.>为什么要判断是否为空?
    因为程序运行时,第一次访问为空,而第二次访问就已经加载了,不为空了,所以需要判断 if (_pictures == nil),这样就避免了重复加载数据
     4.>易错点bug: 为什么代码"//1"这里不用NSString stringWithFormat: 而"//2"这里要使用? 
      
      解析:
        NSDictionary *dict=self.picture[self.index];
        self.jieshaoLabel.text=dict[@"desc"];
     
           第一种解释:这里使用的就是里面的属性, 所以可以直接用,
                          //dict[@"desc"]==等效于[NSString stringWithFormat:@"%@",dict[@"desc"]];
           第二种解释:  因为这里直接就可以引用字典中的键值对的数据了,而下面的self.suoyinLabel.text需要拼接组合数据,需要通过调用其他的属性来组成,所以需要用;
        
     5.>"//2"这里为什么使用的是%ld 来作为占位符?
     @"%ld” ,self.picture.count;    
    这里是很多人都容易忽视的,所以也比较容易出现错误,
    解析:
       首先我们来看看count这个属性的底层实现:
        @property (readonly) NSUInteger count;
    从这个底层我们可以看得出,count是一个NSUInteger类型的,
    而NSUInteger的底层又是什么呢? 我们来看看:如下:

    #if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64

    typedef long NSInteger;

    typedef unsigned long NSUInteger;

    #else

    typedef int NSInteger;

    typedef unsigned int NSUInteger;

    #endif

    可以看出,NSUInteger就是一个别名,而且是两种情况,

    那就是如果你的设备是32位的,那么这个NSUInteger表示的就是给unsigned long取的一个别名,

    那就是如果你的设备是64位的,那么这个NSUInteger表示的就是给 long取的一个别名,

    所以,在使用过程中,我们首先要确定的就是当前编译器环境是处于32位,还是64位环境中,只有确定了这一步,这个bug才能避免!

     

  • 相关阅读:
    Web Api系列教程第2季(OData篇)(一)——OData简介和一个小应用
    漫步ASP.NET MVC的处理管线
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【十】——使用CacheCow和ETag缓存资源
    工具分享——将C#文档注释生成.chm帮助文档
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【外传】——Attribute Routing
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【九】——API变了,客户端怎么办?
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性
    C#基础——谈谈.NET异步编程的演变史
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【七】——实现资源的分页
    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【六】——实现资源间的关联
  • 原文地址:https://www.cnblogs.com/anRanTimes/p/5035881.html
Copyright © 2011-2022 走看看