专栏首页慎独Swift3中的Array内存地址和关联对象的问题

Swift3中的Array内存地址和关联对象的问题

直接用OC的关联对象

空数组

//
//  ViewController.swift
//  SwiftRunner
//
//  Created by Ferris on 2018/1/27.
//  Copyright © 2018年 Ferris. All rights reserved.
//

import UIKit

var objc_associate_ket_array:UInt8 = 0
var objc_asssciate_key_object:UInt8 = 1
extension Array{
    var fg_identify:String{
        set{
            objc_setAssociatedObject(self, &objc_associate_ket_array, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            if let rs = objc_getAssociatedObject(self, &objc_associate_ket_array) as! String?{
                return rs
            }else{
                return "没有关联对象"
            }
        }
    }
}
extension NSObject{
    var fg_tag:String{
        set{
            objc_setAssociatedObject(self, &objc_asssciate_key_object, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            return objc_getAssociatedObject(self, &objc_asssciate_key_object) as! String
        }
    }
}
class ViewController: UIViewController {

    let object_a = NSObject()
    let object_b = NSObject()
    let object_c = NSObject()
    
    var array_a:[NSObject] = []
    var array_b:[NSObject] = []
    var array_c:[NSObject] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        object_a.fg_tag = "a"
        object_b.fg_tag = "b"
        object_c.fg_tag = "c"
        
        array_a.fg_identify = "a"
        array_b.fg_identify = "b"
        array_c.fg_identify = "c"
        // Do any additional setup after loading the view, typically from a nib.
    }
    override func viewDidAppear(_ animated: Bool){
        super.viewDidAppear(animated)
        print("object_a = \(object_a.fg_tag)")
        print("object_b = \(object_b.fg_tag)")
        print("object_c = \(object_c.fg_tag)")
        print("array_a = \(array_a.fg_identify)")
        print("array_b = \(array_b.fg_identify)")
        print("array_c = \(array_c.fg_identify)")
    }
}

输出结果如下

object_a = a
object_b = b
object_c = c
array_a = c
array_b = c
array_c = c

也就是说三个数组全都指向同一个关联对象,为了证实三个数组的内存地址是否一致,直接打印地址 修改get函数

        get{
                        print("\(UnsafeRawPointer(self))")
            if let rs = objc_getAssociatedObject(self, &objc_associate_ket_array) as! String?{
                return rs
            }else{
                return "没有关联对象"
            }
        }

得到输出

0x02504cb0
array_a = c
0x02504cb0
array_b = c
0x02504cb0
array_c = c

居然真的一样!!

非空数组

内含OC对象

给数组加上object_a对象

        array_a.append(object_a)
        array_b.append(object_b)
        array_c.append(object_c)

得到的结果

object_a = a
object_b = b
object_c = c
0x7af37274
array_a = a
0x7c241854
array_b = b
0x7c241884
array_c = c

完全正常,和预想的一致

内含Swift对象

将数组改成

    var array_a:[Any] = []
    var array_b:[Any] = []
    var array_c:[Any] = []

其余代码不变 输出结果变为

0x7a968424
array_a = 没有关联对象
0x7a874964
array_b = 没有关联对象
0x7a874994
array_c = 没有关联对象

关联对象失效了! 将Any换为String等Swift对象类型,依旧一样

查看内存地址

    var fg_address:String{
        get{
            return "\(UnsafeRawPointer(self))"
        }
    }

修改代码如下

   let object_a = NSObject()
    let object_b = NSObject()
    let object_c = NSObject()
    
    var array_a:[Any] = []
    var array_b:[Any] = []
    var array_c:[Any] = []
    
    var mix_array:[[Any]] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        object_a.fg_tag = "a"
        object_b.fg_tag = "b"
        object_c.fg_tag = "c"
        
        
        array_a.append(object_a)
        array_b.append(object_b)
        array_c.append(object_c)
        
        array_a.fg_identify = "a"
        array_b.fg_identify = "b"
        array_c.fg_identify = "c"
        
        mix_array.append(array_a)
        mix_array.append(array_b)
        mix_array.append(array_c)
        
        mix_array.fg_identify = "mix"
        // Do any additional setup after loading the view, typically from a nib.
    }
    override func viewDidAppear(_ animated: Bool){
        super.viewDidAppear(animated)
        print("object_a = \(object_a.fg_tag)")
        print("object_b = \(object_b.fg_tag)")
        print("object_c = \(object_c.fg_tag)")
        print("array_a = \(array_a.fg_identify) + \(array_a.fg_address)")
        print("array_b = \(array_b.fg_identify) + \(array_b.fg_address)")
        print("array_c = \(array_c.fg_identify) + \(array_c.fg_address)")
        
        print("mix_array0 = \(mix_array[0].fg_identify) + \(mix_array[0].fg_address)")
        print("mix_array1 = \(mix_array[1].fg_identify) + \(mix_array[1].fg_address)")
        print("mix_array2 = \(mix_array[2].fg_identify) + \(mix_array[2].fg_address)")
    }

输出

array_a = 没有关联对象 + 0x7bf86cc4
array_b = 没有关联对象 + 0x7bf86a64
array_c = 没有关联对象 + 0x7bf86a94
mix_array0 = 没有关联对象 + 0x7bf86cc4
mix_array1 = 没有关联对象 + 0x7bf86a64
mix_array2 = 没有关联对象 + 0x7bf86a94

当数组被放进另一个数组时,会发现内存地址是一样的。 如果把array_a的类型改成[NSObject]呢,神奇的事情出现了

 var array_a:[NSObject] = []

输出

array_a = a + 0x0000610000053e80
array_b = 没有关联对象 + 0x0000610000260da0
array_c = 没有关联对象 + 0x0000610000260de0
mix_array0 = 没有关联对象 + 0x00006080002664a0
mix_array1 = 没有关联对象 + 0x0000610000260da0
mix_array2 = 没有关联对象 + 0x0000610000260de0

当a被放进另外一个数组的时候,内存地址变了!并且a本身也能拿到关联对象

    var array_a:[NSObject] = []
    var array_b:[NSObject] = []
    var array_c:[NSObject] = []

输出

object_a = a
object_b = b
object_c = c
array_a = a + 0x00006180000496e0
array_b = b + 0x0000618000049260
array_c = c + 0x0000618000048540
mix_array0 = 没有关联对象 + 0x000061800026c320
mix_array1 = 没有关联对象 + 0x000061800026c460
mix_array2 = 没有关联对象 + 0x000061800026c4a0

输出!

object_a = a
object_b = b
object_c = c
array_a = a + 0x000061000005a8d0
array_b = b + 0x000061000005ae10
array_c = c + 0x000061000005ae40
mix_array0 = a + 0x000061000005a8d0
mix_array1 = b + 0x000061000005ae10
mix_array2 = c + 0x000061000005ae40

如果给空数组设置关联对象呢?

测试代码:改变一下位置

        array_a.fg_identify = "a"
        array_b.fg_identify = "b"
        array_c.fg_identify = "c"
        
        array_a.append(object_a)
        array_b.append(object_b)
        array_c.append(object_c)

输出

object_a = a
object_b = b
object_c = c
array_a = 没有关联对象 + 0x0000618000244610
array_b = 没有关联对象 + 0x00006180002441f0
array_c = 没有关联对象 + 0x00006180002444f0
mix_array0 = 没有关联对象 + 0x0000618000244610
mix_array1 = 没有关联对象 + 0x00006180002441f0
mix_array2 = 没有关联对象 + 0x00006180002444f0

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • UIViewController生命周期分析

    xferris
  • html2canvas图片模糊解决方案

    页面采用ViewPort方案,解决iOS上的1px的边框问题,采用这个方案,在iOS上渲染出来的Dom会自动乘以devicePixelRatio,因此iOS上的...

    xferris
  • Kali Linux的Parallels Tools填坑记录

    点击安装parallels tools的时候,会有提示框,提示权限问题,如果直接运行install脚本,提示权限不够,官方推荐的做法:

    xferris
  • Laravel数据库读写分离配置的方法

    公司数据库架构为一主多从,从库访问地址为唯一地址,该处方便负载均衡及扩展从库。所以最终线上采用的配置

    砸漏
  • 冒泡法排序

    冒泡排序的基本概念是: 依次比较相邻的两个数, 将小数放在前面, 大数放在后面。 即在第一趟, 首先比较第1个和第2个数, 将小数放前, 大数放后。 然后比较...

    beginor
  • 二叉堆

    在我们用代码实现二叉堆之前,我们先了解一下几个技巧,二叉堆由于采用数组进行存储,所以我们定位一个节点只需要确认该节点在数组中的下表即可。

    shysh95
  • 003-二维数组的查找

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个...

    单车变摩托
  • 一起来用python实现一下十大经典排序算法

    既然之前很多小伙伴反应希望公众号多发点算法类的文章,那就来呗。先从简单的入手好了,带大家用python来实现一波十大经典排序算法呗。分别是:

    double
  • 基础算法(二)

            上一篇:基础算法(一)         1. 冒泡排序(BubbleSort)         原理:依次比较相邻的两个数,将小数放在前面,大数...

    高爽
  • JS 数组去重(数组元素是对象的情况)

    但当数组元素是对象时,就不能简单地比较了,需要以某种方式遍历各值再判断是否已出现。

    书童小二

扫码关注云+社区

领取腾讯云代金券