A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始



1. 思考1个问题.

    要表示1个坐标.需要两个数据来表示.

    1个是x坐标 1个是y坐标.

    x坐标和y左边联合起来表示 界面上的1点.

    1个坐标需要两个数据表示.

    结构体和类的区别:

    1). 结构体是由多个小变量组合而成的. 结构体中只能有属性.

        对象中既有小变量,还可以有方法.  对象中即可有有属性也可以方法.

    2). 结构体变量是存储在栈区.

        对象是存储在堆区的.

        在内存中栈区相对较小.但是栈区的数据访问效率要高.

        堆区相对较大,但是堆区的数据访问效率相对较低.

    3). 虽然栈区的空间访问效率相对较块,但是千万不要把所有的数据都一股脑的全存储在栈区

        因为栈区空间较小,如果都存储在栈区 反而会影响性能.

    4). 什么时候使用类.

        如果封装的这个数据 既有属性也有方法, 只能使用类.

        如果封装的数据只有属性.

        如果这是1个轻量级的数据,就使用结构体. 属性很少.

        如果这是1个重量级的数据 就使用类. 属性很多.

        轻量级使用结构体.

        重量级使用类.

    很明显要保存1个点.使用结构体是最合适的 因为它只有两个属性.

    ------

    幸运的是,如果我们真的要去保存1个控件的坐标 我们不需要去自己定义结构体类型.

    因为这个结构体Foundation框架中已经定义好了.我们要用直接声明变量就可以了.

   

     CGPoint这是它的定义.

     struct CGPoint {

        CGFloat x;

        CGFloat y;

     };

     typedef struct CGPoint CGPoint;

    这个结构体就是来表示控件的坐标的. CGFloat 就是double

    typedef CGPoint NSPoint;

    CGPoint完全等价于NSPoint.

    CGPoint初始化的方式.

    1). 先声明CGPoint变量 然后再初始化属性.

         CGPoint p1;

         p1.x = 10;

         p1.y = 20;

         

    2).  CGPoint p1 = {10,20};

    3).  CGPoint p1 = {.x = 20, .y = 30};

    4). 使用系统自带的函数来快速的创建CGPoint变量.

        CGPoint p1 =  CGPointMake(10, 20);

        CGPoint p1 =  NSMakePoint(10, 20);

    5). 使用函数将CGpoint变量转换为字符串.

        NSStringFromPoint();

        

2.  思考:

     请定义1个变量来保存1个控件的尺寸.

     如果我们要保存1个控件的尺寸,而1个控件的尺寸是由1个宽度和高度组合而成的.

     使用结构体来最合适.

     CGSize

     这是它的定义.

     struct CGSize {

        CGFloat width; //宽度

        CGFloat height; //高度

     };

     typedef struct CGSize CGSize;

     typedef CGSize NSSize;

     NSSize完全等价于CGSize

     

     这个结构体的作用: 保存1个控件的尺寸.

     ----CGSize的初始化-------

     CGSize s1 =  CGSizeMake(100, 200);

     CGSize s2 =  NSMakeSize(100, 200);

     

     将CGSize结构体变量转换为字符串.

     NSLog(@"%@",NSStringFromSize(s1)

3. CGRect.

     这是它的定义.

     struct CGRect {

        CGPoint origin; //代表控件的坐标

        CGSize size; //控件的尺寸.

     };

     typedef struct CGRect CGRect;

     这个CGRect类型的变量 是来保存1个控件的坐标和尺寸.

     

     typedef CGRect NSRect;

     NSRect和CGRect完全等价.

   

    ----初始化-----

     CGRect r1 =  CGRectMake(10, 20, 100, 200);

     CGRect r2 =  NSMakeRect(10, 20, 100, 200);

     

     将CGRect变量转换为字符串.

     NSLog(@"%@", NSStringFromRect(r1));

     平时使用我们还是使用CGXX 虽然NSXX效果一样.



1.  集合中只能存储OC对象.无法存储基本数据类型.

     基本数据类型就无法存储.

     但是我就是要把基本数据类型存储到集合中 怎么办?

     想法:

     先把基本数据类型包装到1个OC对象中. 然后再将这个OC对象存储到集合中.

     幸运的是: 包装基本数据的类型的那个类.Foundation框架已经写好了.

     NSNumber

     存储基本数据类型到集合中的原理:

     1). 先将基本数据类型存储到NSNumber对象中.

     2). 然后再将NSNumer对象存储到集合中.

     3). 从集合中取值元素的值 取出来是1个NSNumebr对象. 真正的数据是存储在这个对象里的.

     注意: 要包装什么类型的数据,在使用类方法包装的时候要调用对应的方法.

          从NSNumber取值的时候 你包装的是什么类型的数据在其中,就要调用对应的 xxxValue方法.

2. 简要创建NSNumber对象的形式.

    @20;  记住,这不是1个整型的20  而是1个NSNumber对象.这个对象中包装的是整型的20

    注意: 如果是1个变量.就需要使用小括弧括一下.

         

    int num  = 10;

    NSNumber *num1 = @(num);


NSValue

     集合中是无法存储基本数据类型的.包括结构体

     只能存储OC对象.

     NSValue来包装结构体数据的以便将其间接的存储到集合中.


NSDate: 处理日期与时间的1个类.

    1).可以得到当前系统的时间.

       直接创建1个NSDate对象,这个对象中存储的就是当前系统的格林威治时间.

       NSDate *date = [NSDate date];

    2).默认输出的时间格式: 2020-03-28 07:47:37 +0000

                        2020/3/28 7:47:37

         自定义日期的输出格式.

         NSDate *date = [NSDate date];

         

         //1.先创建1个日期格式化对象.这个对象的功能,可以按照指定的格式将1个日期转换为1个字符串.

         NSDateFormatter *formatter = [NSDateFormatter new];

         //2.指定要转换的格式.

         //y 年 写4个y 表示用4位来表示年.

         //M 月

         //d 天

         //h 12小时制的小时.

         //H 24小时制的小时.

         //m 分钟

         //s 秒

         //你完全可以自定义这个格式.

         formatter.dateFormat = @"yy年M月dd日 hh点mm分ss秒";

         

         //3.按照指定的格式将日期转换为指定的格式的字符串.

         

         NSString *str =  [formatter stringFromDate:date];

         用这种方式转换以后,会自动的转换为当前时区的时间.

         

    3). 将字符串转为为日期对象.

         NSString *str = @"2020/12/12 13:12:12";

         NSDateFormatter *formatter = [NSDateFormatter new];

         formatter.dateFormat = @"yyyy/MM/dd HH:mm:ss";

         NSDate *date =  [formatter dateFromString:str];

         NSLog(@"date = %@",date);

         


2. 在当前时间的基础之上加指定的秒数以后是多久.

    + (instancetype)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs

3. 计算两个时间之差.

    - (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate;

4. 得到日期对象的各个部分.

    1). 使用NSDateFormatter来拿到每一部分.

    2). 另外一种更加复杂的方法.


深拷贝与浅拷贝


1. 结论:

    无论在ARC模式下,还是在MRC模式下.如果1个对象的属性是NSString类型的.

    @property参数.不要写retain、strong、weak.

    而是用copy.

    强调: 只有当属性的类型是NSString的时候,@property参数才使用copy

2. copy是1个方法.定义在NSObject类中.

    所以所有的OC类都有这个方法,包括NSString.

    copy方法的作用: 复制1个对象.重新来1个一模一样的对象. 对象的属性的值相同.

    测试1下 字符串的copy方法.

    NSString --> copy --> NSString 这个时候,没有产生新对象.像这样的拷贝叫做浅拷贝.

                                   没有产生新对象,而是直接将原来那个对象的地址返回.

    NSMutableString -> copy -> NSString 这个时候,有新对象的产生,像这样的拷贝叫做深拷贝.

                                    有产生新对象.

    mutableCopy方法.也是拷贝对象.

    NSString -> mutableCopy --> NSMutableString  深拷贝.

    NSMutableString -> mutableCopy -> NSMutableString 深拷贝.

    总结:

    只有对象是NSString的时候 copy 才是浅拷贝.

    其他都是深拷贝.

    copy 出来的都是不可变字符串

    mutableCopy出来的都是可变字符串.


单例设计模式.

    单例:单个实例. 单个对象.

    1个类的对象,无论在何时创建,无论创建多少次.创建出来的对象都是同1个对象.

2. 创建对象的方法.

    + alloc 方法 这个方法才是真正的在内存中申请空间创建对象.

    其实这个方法什么事情都没有做. 只是调用另外1个 + allocWithZone:方法.

    正儿八经的在内存中申请空间创建对象的事情 其实是+ allocWithZone:方法.

    alloc方法的内部只是调用了+ allocWithZone:方法.


3. 如何实现单例模式.

     + (instancetype)allocWithZone:(struct _NSZone *)zone

     {

     

         static id instance = nil;

         if(instance == nil)

         {

            instance =   [super allocWithZone:zone];

         }

         return instance;

     }

     

     

     zone: 参数是没有任何意义的.

4. 单例的规范.

    1). 如果我们的类设计为了单例模式.

        要求为这个类提供1个类方法 来快速的得到这个单例对象.

        这个类方法的名称的规范:  defaultXXXX;


                             sharedXXXX;

5. 有什么用?

    1). 单例的特点

        无论何时、无论何地、无论创建多少次,得到的都是同1个对象.

        意味着这个单例对象中的属性的值被共享.

    2). 如果有一些数据.程序中的所有的地方都要使用.

        如何共享这个数据?

        游戏面板的宽度和高度.

        width = 800;

        height = 600;

        当有一些数据需要共享给别的类的时候,就可以把这些数据存在单例对象中.




0 个回复

您需要登录后才可以回帖 登录 | 加入黑马