美文网首页
搞清楚OC的形参(NSMutableArray...等)

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

作者: ibingewin | 来源:发表于2018-08-18 15:07 被阅读29次

搞清楚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,方法有两种:

  • 传值NSMutableArray **:用指针的指针就可以进行赋值操作,就好比C中的int,其实系统就有很多这样的操作,例如常用的NSError,都是传值&error,这样才能在内部处理错误后,返回上来;
  • 不要用=赋值,只用OC的方法调用:如添加元素就用addObject:,移除就removeObject:

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

相关文章

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

    搞清楚OC的形参(NSMutableArray...等) 前提:近期在封装一个算法的时候,发现在方法中传递一个NS...

  • iOS入门小知识-Swift内外参数名

    形参和实参 以OC为例,在方法的声明中,有不带参的,也有带参的,在调用带参方法的时候,参数可分为形参和实参,形参好...

  • OC中的集合

    OC中的集合包含哪些? 包括NSArray、NSDictionary 和它们对应的子类NSMutableArray...

  • swift

    swift 函数 一、函数的定义函数的定义格式 形参列表的格式形参名1: 形参类型1, 形参名2: 形参类型2, ...

  • js自定义类&自定义对象

    自定义类: function 类名(形参1,形参2){ this.属性1=形参1; this.属性2=形参2; t...

  • Swift-函数基础

    一、函数 1、定义 1、声明:func 函数名(形参名:形参类型,形参名:形参类型)-> 返回值类型 2、调用:函...

  • swift函数基础知识

    1、函数声明和调用 通用函数声明格式:func 函数名称(形参名:形参类型,形参名:形参类型,···)->返回值类...

  • ES6形参默认值19-10-17

    1.形参的默认值 --当不传入形参的时候默认使用形参的默认值

  • 形参

    编程中有时候递归需要保存当前的状态,那么传递的如果是形参的话,返回的时候父节点的值就不会变了。 例如 C++ 的 ...

  • Java Arrays

    查找——binarySearchStatic int binarySearch(形参)=====各种形参不同的方...

网友评论

      本文标题:搞清楚OC的形参(NSMutableArray...等)

      本文链接:https://www.haomeiwen.com/subject/zbsfiftx.html