iOS技术积累

不管生活有多不容易,都要守住自己的那一份优雅。

情报局(1)

2017-01-13

  1. NSArray 用 copy 和 Strong修饰的区别

例如 self.a = b;
对于不可变对象来说使用copy,和Strong都可以。
copy的话对于setter方法,如果对方传进来的是b 不可变对象,那么copy之后a还是不可变对象,别的地方修改了b对a不会影响。
如果传进来的b是可变对象,那么copy之后a是不可变对象,修改b还是不会对a造成影响。

strong对于setter方法, 如果对方传进来的是b 不可变对象,那么copy之后a还是不可变对象,别的地方修改了b对a不会影响。
如果传进来的b是可变对象,那么copy之后a是不可变对象,修改b就会对a造成影响。

综上: 对于不可变对象应当使用copy修饰符

  1. NSMutable 用 copy 和 Strong修饰的区别
    例如 self.a = b;
    假设使用的是copy,无论传递进来的是什么,copy之后都会将a变成不可变对象。但是我们明明声名的是可变对象。这时候我们如果使用了 add, remove等方法时,就会抛出
    unregonrized selector method for xx 经典错误。 因为我们声名的Mutable对象经过赋值之后就变成了imMutable对象。

综上: 对于可变对象应当使用 strong操作符

  1. 对NSArray及其子类做MutableCopy是深拷贝还是浅拷贝

    首先补充 对于copy方法,无论源对象是可变还是不可变, 使用了copy生成的都是不可变对象,
    对于MutableCopy方法,无论源对象是可变还是不可变, 使用了copy生成的都是不可变对象。

由于容器里面存的只是目标对象的指针,在做mutablecopy或者copy只是让容器变成是否可修改的,并不会修改容器内部指针所指向的内存地址。所以都是浅拷贝

2017-01-16

给出以下代码, 问 在block嵌套的时候是否需要 嵌套 weak strong dance?


@interface A : NSObject
@property (nonatomic, copy) dispatch_block_t block;
@end

@implementation A



- (void)dealloc {
    NSLog(@"%@ dealloc ",[self class]);
}


@end
@interface B : NSObject
@property (nonatomic, copy) dispatch_block_t block;
@end

@implementation B

- (void)dealloc {
    NSLog(@"%@ dealloc ",[self class]);
}

@end
#define  weakify(A) __weak typeof((A)) A##__w = A;
#define  strongify(A)  __strong typeof((A)) A = A##__w ;
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
//    [self test1];
    [self test2];
}

- (void)test1 {
    A *a = [A new];
    weakify(a)
    a.block = ^{
        strongify(a)
        NSLog(@"%@",[a class]);
        B *b = [B new];
        b.block = ^{
            NSLog(@"%@",[a class]);
        };
    };
    a.block();
}

- (void)test2 {
    A *a = [A new];
    B *b = [B new];

    weakify(b) weakify(a)
    a.block = ^{
        strongify(a) strongify(b)
        NSLog(@"%@",[b class]);
        NSLog(@"%@",[a class]);

        b.block = ^{
            NSLog(@"%@",[b class]);
            NSLog(@"%@",[a class]);
        };
    };
    a.block();
    b.block();
}
@end

补充: #define weakify(A) weak typeof((A)) A##w = A;

这行宏语法是说明我声明一个weak的变量 名字为A__w ##在宏指令的作用是拼接

答: 具体需要看情况而定:很多人使用block的时候不去追究原理而是一味的死记硬背的记住要循环使用weak strong。
这里首先说明的是block只会捕获以下变量。 除了全局变量,block参数, block的内部变量 外的所有变量
并且,block持有这些变量的时机是在编译时期决定的,而不是运行时期。 所以只要block内只要出现了上述类型的变量就会去持有。

test1: a.block在内部出现了a这个外部变量,需要捕获a,为了避免出现循环引用我们是需要对a 使用weak strong 的,
在a.block()执行期间内部初始化了变量b 并且变量b.block捕获了a。a并没有捕获b,所以这时候出现的情况是 b.-> block -> a
a.block在执行完毕只会会释放变量b。随之释放.

test2: a.block内部出现了a,b的变量,但是此刻b并没有持有a,所以在外层block的时候只存在a->block-> (a,b) 并不存在 b->a,
所以为了避免循环引用,只需要对a使用weak strong。
在执行a.block的时候,在这个时刻,a->block->(a,b) (这是前提条件)。b.block持有了 a,b ,由于b->block->b,所以需要对b使用
weak strong,并且在此时刻 a->block->b 并且 b->block->a,出现了循环引用环,所以需要内部再出现一次 weak strong。
代码改写后为:


    A *a = [A new];
    B *b = [B new];

    weakify(a)
    a.block = ^{
        strongify(a)
        NSLog(@"%@",[b class]);
        NSLog(@"%@",[a class]);

        weakify(a) weakify(b)
        b.block = ^{
            strongify(a) strongify(b)
            NSLog(@"%@",[b class]);
            NSLog(@"%@",[a class]);
        };
    };
    a.block();
    b.block();

之前有人也提出问题说,我有时候也会用block关键字,这里我想说的是 block是说在捕获基本数据类型的时候捕获的是readonly(其实是一份副本)的值
如果我想修改这个值的话,使用__block关键字,这样在编译的时候传递进去的就是指针,和外部是一个值,
这里的问题是如何避免block捕获变量带来的内存泄漏的问题的分析。

阅读更多

制作Swift和Objective-C Mixed的Pod

    • 知识背景

      1. What is CocoaPods
      2. What did CocoaPods do?

      In Xcode, with references directly from the ruby source, it:

      1. Creates or updates a workspace.
      2. Adds your project to the workspace if needed.
      3. Adds the CocoaPods static library project to the workspace if needed.
      4. Adds libPods.a to: targets => build phases => link with libraries.
      5. Adds the CocoaPods Xcode configuration file to your app's project.
      6. Changes your app's target configurations to be based on CocoaPods's.
      7. Adds a build phase to copy resources from any pods you installed to your app bundle. i.e. a 'Script build phase' after all other build phases with the following:
      • Shell: /bin/sh
      • Script: ${SRCROOT}/Pods/PodsResources.sh

    大意是,CocoaPods是一个依赖管理工具,使用CocoaPods可以自动的去分析依赖,然后通过脚本去将第三方依赖复制编译为静态库然后链接进项目。~~~等。

    • 制作Pod

    有时候我们有把代码做成一个轮子给别人用情况,我们需要按照官方的教程Making CocoaPods去制作。

    教程分为2类 :

    1. 发布公共Pod给所有开发者使用。
    2. 制作私有Pod。 方法较为简单。自行查阅资料即可。这里不再赘述。

    • Swift和Objective-C Mixed

      参考官方的文档(文末指出),混编里面包含有2种调用情况:

      Question1. Swift调用Objective-C
      Question2. Objective-C调用Swift

    这里我新建一个项目 命名为Mixed(Single View Application), 创建一个文件夹Classes用于存放源代码
    创建一个Objective-C Class O 继承自NSObject 创建一个Swift Class S 继承自NSObject

    • Answer1: 为Swift源代码添加一个 XXX.h头文件这里为Mixed-Bridging-Header 在这个文件中导入需要访问的Objective-C 源代码的头文件。

    headerConfig

    有时候Xcode反应会稍微延迟一点。手动编译一下即可。做完这个配置,Swift即可访问Objective-C 源代码。
    代码如图:
    swiftAccessObjc

    • Answer2: Objective-C 访问Swift源代码 需要导入系统为项目生成的头文件,默认为Module+Swift.h 当然自己也是可以修改的, 导入之后,编译一下(Xcode有时候有缓存,没事就应该编译一下
    阅读更多