• 《Programming with Objective-C》第四章 Encapsulating Data


    Designated Initializer

    不稳定的传送门 

    合成属性

    Properties don’t always have to be backed by their own instance variables.

    As an example, the XYZPerson class might define a read-only property for a person’s full name:

    @property (readonly) NSString *fullName;

    Rather than having to update the fullName property every time the first or last name changed, it would be easier just to write a custom accessor method to build the full name string on request:

    - (NSString *)fullName 
    {
        return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
    }

      假如一个属性是另外2个属性的复合体,那么可以重写该属性的getter方法,在方法中返回2个属性的结合,就不用每次更新2个属性的时候去更新这个复合属性啦

    Lazy Factory

    (1)Using a factory method to get instances of a class (factory method pattern)【还不是很了解,Todo:继续查找资料】

    (2)Store the instances in a map, so you get the same instance the next time you ask for an instance with same parameter (multiton pattern)【项目里搜索模块将多个viewController存在一个dictionary里,当从dictionary读不到的时候就创建一个并写入】

    (3)Using lazy initialization to instantiate the object the first time it is requested (lazy initialization pattern)【按需创建】

    关于Strong属性

    Strong Reference Cycles

    Memory for Objective-C objects is allocated dynamically (on the heap), which means you need to use pointers to keep track of an object’s address.

    In Objective-C, an object is kept alive as long as it has at least one strong reference to it from another object.

      如图,如果XYZPerson没有被释放,则firstName和lastName也永远不会被释放。

      

      UITableView.h中,对delegate和dataSource的声明方式如下  

    @property (nonatomic, weak, nullable) id <UITableViewDataSource> dataSource;
    @property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;

      注意到,delegate和dataSource都是weak而不是strong,为什么呢?

      比如,现在我们创建一个具有UITableView的Controller,则该Controller中声明UITableView如下:

    @property UITableView *tableView;

      注意,@property默认是strong的,回到刚刚那个问题,如果delegate是strong会发生什么事情呢?当我们为该tableView设置delegate的时候,即

    tableView.delegate = self;

      此时Controller和TableView的关系如下:

      这2个Object相互之间是strong关系,就是说已经产生了Strong Reference Cycle,我们知道"An object is kept alive as long as it has at least one strong reference to it from another object.",那么这2个冤家就永远你中有我,我中有你,谁也不释放谁了。死锁!

      解决方法就是将其中一个关系改为weak,明显将delegate属性声明为weak是合理的,UITableView也是这样做的。dataSource属性同理。所以结论就是,任何delegate的属性都不应该为strong

    局部变量,默认是__strong

      为什么默认是__strong而不是__weak呢?因为方便!所有默认值的设置就是为了方便。

    NSDate *originalDate = self.lastModificationDate;
    self.lastModificationDate = [NSDate date];
    NSLog(@"Last modification date changed from %@ to %@",
    originalDate, self.lastModificationDate);
    
    NSDate *__weak originalDate = self.lastModificationDate;
    self.lastModificationDate = [NSDate date];
    NSLog(@"Last modification date changed from %@ to %@",
    originalDate, self.lastModificationDate);

      以上2段代码的区别就是,第一段没问题,第二段,当self.lastModificationDate重新被赋值之后,它原本所指向的内存已经没有strong指针指向了,只有一个weak的originalDate指着,此时这块内存极有可能被系统释放掉。originalDate就成了悬浮指针。

      所以大部分情况下还是要使用__strong的,自然默认值为__strong也就合情合理了。

    多线程中的strong与weak

    In situations like this, you might want to cache the weak property in a strong variable to ensure that it is kept in memory as long as you need to use it:

    - (void)someMethod 
    {
        NSObject *cachedObject = self.weakProperty;
        [cachedObject doSomething];
        ...
        [cachedObject doSomethingElse];
    }

      

      要时刻测试weak属性是否还存在啊,如下:

    if (self.someWeakProperty) 
    {
            [someObject doSomethingImportantWith:self.someWeakProperty];
    }

      但是这就够了吗?并不是,多线程下,应该这样

     NSObject *cachedObject = self.someWeakProperty;              // 1
        if (cachedObject) {                                       // 2
            [someObject doSomethingImportantWith:cachedObject];   // 3
        }                                                         // 4
        cachedObject = nil;                                       // 5

      Todo:多线程的知识还是得补补,这里不是很懂

    关于Copy属性

    copy属性与NSMutableString

    假如当前Controller有以下属性:

    @property NSString *firstName;

    在某个地方

    NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
    self.firstName = nameString;  //此时指向了NSMutableString
    [nameString appendString:@"ny"];

    self.firstName的值为"Johnny",一个应为NSString*的值却莫名其妙被修改了?因为它指向了一个它不该指向的地方。

    解决方案如下,为firstName添加copy属性

    @property (copy) NSString *firstName;

    在某个地方

    NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
    self.firstName = nameString;  //此时self.firstName指向的是nameString的copy版本,该版本是NSSting类型,且对这个版本的String对象持strong指针
    [nameString appendString:@"ny"];

     self.firstName的值为"John",它与nameString指向的是两个完全不同的地方。

    将传入的参数copy一份复制给成员变量

    - (id)initWithSomeOriginalString:(NSString *)aString {
        self = [super init];
        if (self) {
            _instanceVariableForCopyProperty = [aString copy];
        }
        return self;
    }

    假如不想让成员变量与传入的参数共同指向一个地方,那么只要copy一份就可以啦

    Any object that you wish to set for a copy property must support NSCopying

    Nothing

  • 相关阅读:
    Spring Security 记住我功能 详解
    浅谈前端SPA(单页面应用)
    Token问什么可以避免CSRF/XSRF?
    总结 XSS 与 CSRF 两种跨站攻击
    localStorage,sessionStorage和cookie的区别及使用
    cookie,token验证的区别
    彻底弄懂session,cookie,token
    HTTP cookies 详解
    纯css3实现文字间歇滚动效果
    我的less学习之路
  • 原文地址:https://www.cnblogs.com/chenyg32/p/4856246.html
Copyright © 2020-2023  润新知