搞清楚OC的形参(NSMutableArray...等)

2018-08-18  本文已影响29人  ibingewin

搞清楚OC的形参(NSMutableArray...等)

前提:
近期在封装一个算法的时候,发现在方法中传递一个NSMutableArray类型的array,在方法中对其再赋值,等方法执行完之后,发现array并没有变化,导致出现问题,虽然当时很快的找到了解决方法,但原因到底是什么,明白的并不够彻底,现今有空,回头梳理一下

先回顾一下我的问题,代码如下:

- (void)test_passObject {
    NSMutableArray *arr = [NSMutableArray arrayWithCapacity:0];
    [self pass:arr];
}
- (void)pass:(NSMutableArray *)arr {
    arr = @[@"a"].mutableCopy;
}

我的本意是希望在[self pass:arr]之后能够得到一个新的arr,但实际结果却是这样

前:0x600000246510,(
)
后:0x600000246510,(
)

纳尼!居然没有变化!最直观的调试在pass方法中打印一下就清楚了:

- (void)test_passObject {
    NSMutableArray *arr = [NSMutableArray arrayWithCapacity:0];
    NSLog(@"前:%p,%@", arr, arr);
    [self pass:arr];
    NSLog(@"后:%p,%@", arr, arr);
}
- (void)pass:(NSMutableArray *)arr {
    arr = @[@"a"].mutableCopy;
    NSLog(@"中:%p,%@", arr, arr);
}
输出为:
前:0x6000002584b0,(
)
中:0x60000025a8b0,(
    a
)
后:0x6000002584b0,(
)

由此可见,在pass:方法中,传递的arr就像C中的int一样,只是一个值传递,对其的赋值并不会影响外部的实参,为了进一步证实这个观点,我又做了如下尝试:

- (void)test_passObject {
    NSArray *arr = @[@1, @"1", @[@1], @[@1].mutableCopy, [UIView new]];
    for (id obj in arr) {
        NSLog(@"前:%p,%@", arr, arr);
        [self pass:obj];
        NSLog(@"后:%p,%@", arr, arr);
    }
}
- (void)pass:(id)arr {
    arr = @[@"a"].mutableCopy;
    NSLog(@"中:%p,%@", arr, arr);
}
输出为:
------------------------------------------
前:0xb000000000000012,1
中:0x600000257400,(
    a
)
后:0xb000000000000012,1
------------------------------------------
前:0x12641a088,1
中:0x600000257400,(
    a
)
后:0x12641a088,1
------------------------------------------
前:0x604000016fc0,(
    1
)
中:0x6000002578b0,(
    a
)
后:0x604000016fc0,(
    1
)
 ------------------------------------------
前:0x6040002502c0,(
    1
)
中:0x6040002511c0,(
    a
)
后:0x6040002502c0,(
    1
)
-----------------------------------------
前:0x7fc426619df0,<UIView: 0x7fc426619df0; frame = (0 0; 0 0); layer = <CALayer: 0x604000223ba0>>
中:0x600000253590,(
    a
)
后:0x7fc426619df0,<UIView: 0x7fc426619df0; frame = (0 0; 0 0); layer = <CALayer: 0x604000223ba0>>

可以很清楚的看到:的输出完全一样,的任何变化,都对都没有影响,甚至传值为nil也一样。

由此可以得出概论:OC方法中的形参与C函数的形参一样,全都是值传递。对于OC对象而言,其本质是void *指针,所以也就是指针值传递。在方法中,传递的形参就是一个新的指针变量,只是接收了传过来的指针值,之后对其的任何赋值操作,只是修改该指针变量的指向而已,完全不会影响到外部对象。

所以要实现我一开始的初衷:在方法中修改NSMutableArray,方法有两种:

PS: 第二种只适用于可变类型的对象,建议使用第一种方法。其实这都是刚开始学OC时应该清楚的,但当时不知道为什么,了解的不够清楚,导致现在又要回头补习😂,哎!基本功一定要扎实,不然总有让你后悔的时候!

上一篇 下一篇

猜你喜欢

热点阅读