Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Swift3中的Array内存地址和关联对象的问题

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

作者头像
xferris
发布于 2018-06-01 07:40:28
发布于 2018-06-01 07:40:28
96700
代码可运行
举报
文章被收录于专栏:慎独慎独
运行总次数:0
代码可运行

直接用OC的关联对象

空数组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//
//  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)")
    }
}

输出结果如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
object_a = a
object_b = b
object_c = c
array_a = c
array_b = c
array_c = c

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        get{
                        print("\(UnsafeRawPointer(self))")
            if let rs = objc_getAssociatedObject(self, &objc_associate_ket_array) as! String?{
                return rs
            }else{
                return "没有关联对象"
            }
        }

得到输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
0x02504cb0
array_a = c
0x02504cb0
array_b = c
0x02504cb0
array_c = c

居然真的一样!!

非空数组

内含OC对象

给数组加上object_a对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        array_a.append(object_a)
        array_b.append(object_b)
        array_c.append(object_c)

得到的结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
object_a = a
object_b = b
object_c = c
0x7af37274
array_a = a
0x7c241854
array_b = b
0x7c241884
array_c = c

完全正常,和预想的一致

内含Swift对象

将数组改成

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var array_a:[Any] = []
    var array_b:[Any] = []
    var array_c:[Any] = []

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
0x7a968424
array_a = 没有关联对象
0x7a874964
array_b = 没有关联对象
0x7a874994
array_c = 没有关联对象

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

查看内存地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var fg_address:String{
        get{
            return "\(UnsafeRawPointer(self))"
        }
    }

修改代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   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)")
    }

输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array_a = 没有关联对象 + 0x7bf86cc4
array_b = 没有关联对象 + 0x7bf86a64
array_c = 没有关联对象 + 0x7bf86a94
mix_array0 = 没有关联对象 + 0x7bf86cc4
mix_array1 = 没有关联对象 + 0x7bf86a64
mix_array2 = 没有关联对象 + 0x7bf86a94

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var array_a:[NSObject] = []

输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array_a = a + 0x0000610000053e80
array_b = 没有关联对象 + 0x0000610000260da0
array_c = 没有关联对象 + 0x0000610000260de0
mix_array0 = 没有关联对象 + 0x00006080002664a0
mix_array1 = 没有关联对象 + 0x0000610000260da0
mix_array2 = 没有关联对象 + 0x0000610000260de0

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    var array_a:[NSObject] = []
    var array_b:[NSObject] = []
    var array_c:[NSObject] = []

输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

输出!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
如果给空数组设置关联对象呢?

测试代码:改变一下位置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        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)

输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
对象、消息、运行期--10:runtime关联对象
在category中的使用 @property添加属性 ,不会生成带下划线的成员变量,也不会有setter和getter方法实现,所以我们通过runtime关联对象的技术为已经存在的类添加“属性”,这样我们只是实现了setter和getter方法,依然不会有带下划线的成员变量
xy_ss
2023/11/22
2270
iOS开发·runtime原理与实践: 关联对象篇(Associated Object)(应用场景:为分类添加“属性”,为UI控件关联事件Block体,为了不重复获得某种数据)
分类(category)与关联对象(Associated Object)作为objective-c的扩展机制的两个特性:分类,可以通过它来扩展方法;Associated Object,可以通过它来扩展属性;
陈满iOS
2018/09/10
3.1K0
iOS开发·runtime原理与实践: 关联对象篇(Associated Object)(应用场景:为分类添加“属性”,为UI控件关联事件Block体,为了不重复获得某种数据)
iOS底层原理总结 - 关联对象实现原理
面试题 Category能否添加成员变量?如果可以,如何给Category添加成员变量? 答:不能直接添加成员变量,但是可以通过runtime的方式间接实现添加成员变量的效果。 RunTime为Category动态关联对象 使用RunTime给系统的类添加属性,首先需要了解对象与属性的关系。我们通过之前的学习知道,对象一开始初始化的时候其属性为nil,给属性赋值其实就是让属性指向一块存储内容的内存,使这个对象的属性跟这块内存产生一种关联。 那么如果想动态的添加属性,其实就是动态的产生某种关联就好了。而想要
xx_Cc
2018/06/19
1.4K0
【IOS开发高级系列】Objective-c Runtime专题总结
http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/
江中散人_Jun
2023/10/16
4440
【IOS开发高级系列】Objective-c Runtime专题总结
【iOS】关联对象详解
associatedObject又称关联对象。顾名思义,就是把一个对象关联到另外一个对象身上。使两者能够产生联系。目前我能想到的关联对象的使用场景有如下几点:
VV木公子
2018/06/05
7.8K0
【iOS】关联对象详解
iOS Category 添加属性实现原理 - 关联对象
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) { OBJC_ASSOCIATION_ASSIGN = 0, // 指定一个弱引用相关联的对象 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 指定相关对象的强引用,非原子性 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 指定相关的对象被复制,非原子性 OBJC_ASSOCIATION_RETAIN = 01401, // 指定相关对象的强引用,原子性 OBJC_ASSOCIATION_COPY = 01403 // 指定相关的对象被复制,原子性 };
用户1941540
2019/02/15
3.4K0
iOS Category 添加属性实现原理 - 关联对象
【IOS开发进阶系列】IOS常用开发技巧专题
    将AFNetworking添加到预编译头文件,意味着这个框架会被自动的添加到工程的所有源代码文件中。
江中散人_Jun
2023/10/16
6640
【IOS开发进阶系列】IOS常用开发技巧专题
iOS开发·runtime原理与实践: 方法交换篇(Method Swizzling)(iOS“黑魔法”,埋点统计,禁止UI控件连续点击,防奔溃处理)
Method Swizzing是发生在运行时的,主要用于在运行时将两个Method进行交换,我们可以将Method Swizzling代码写到任何地方,但是只有在这段Method Swilzzling代码执行完毕之后互换才起作用。
陈满iOS
2018/09/10
2.9K0
iOS开发·runtime原理与实践: 方法交换篇(Method Swizzling)(iOS“黑魔法”,埋点统计,禁止UI控件连续点击,防奔溃处理)
iOS引用转换:Foundation与Core Foundation对象互相转换(__CFString转NSString,void *转id等等)
下载地址:苹果公开的源代码在这里可以下载,https://opensource.apple.com/tarballs/
陈满iOS
2018/09/10
2.3K0
iOS引用转换:Foundation与Core Foundation对象互相转换(__CFString转NSString,void *转id等等)
Objc Runtime 总结
Objc Runtime使得C具有了面向对象能力,在程序运行时创建,检查,修改类、对象和它们的方法。Runtime是C和汇编编写的,这里http://www.opensource.apple.com/source/objc4/可以下到苹果维护的开源代码,GNU也有一个开源的runtime版本,他们都努力的保持一致。苹果官方的Runtime编程指南
用户7451029
2020/06/16
8540
神经病院 Objective-C Runtime 出院第三天——如何正确使用 Runtime
到了今天终于要"出院"了,要总结一下住院几天的收获,谈谈Runtime到底能为我们开发带来些什么好处。当然它也是把双刃剑,使用不当的话,也会成为开发路上的一个大坑。
一缕殇流化隐半边冰霜
2018/08/30
1.5K0
神经病院 Objective-C Runtime 出院第三天——如何正确使用 Runtime
iOS进阶之runtime作用
前言 Runtime基本是用C和汇编写的,可见苹果为了动态系统的高效而作出的努力。你可以在这里下到苹果维护的开源代码。苹果和GNU各自维护一个开源的runtime版本,这两个版本之间都在努力的保持一致。Objective-C 从三种不同的层级上与 Runtime 系统进行交互,分别是通过 Objective-C 源代码,通过 Foundation 框架的NSObject类定义的方法,通过对 runtime 函数的直接调用。大部分情况下你就只管写你的Objc代码就行,runtime 系统自动在幕后辛勤劳作着。
Dwyane
2018/05/22
6750
iOS内存管理-深入解析自动释放池
iOS开发中的Autorelease机制是为了延时释放对象。自动释放的概念看上去很像ARC,但实际上这更类似于C语言中自动变量的特性。
梧雨北辰
2019/12/24
5.4K3
iOS内存管理-深入解析自动释放池
神奇的Runtime
[receiver message]不是一个简单地方法调用,而是在编译阶段被编译器转化为
Helloted
2022/06/06
7120
神奇的Runtime
iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling你要知道的runtime都在这里
你要知道的runtime都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解runtime相关知识,从原理到实践,由于包含内容过多分为以下五篇文章详细讲解,可自行选择需要了解的方向: 从runtime开始: 理解面向对象的类到面向过程的结构体 从runtime开始: 深入理解OC消息转发机制 从runtime开始: 理解OC的属性property 从runtime开始: 实践Category添加属性与黑魔法method sw
WWWWDotPNG
2018/04/10
8560
iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling你要知道的runtime都在这里
Swift-Runtime总结
      相信每一个iOS开发者都知道Runtime, 现在Swift也更新到5.0+版本了,要是你也学习了Swift的话你可能也会想过这样一个问题,OC大家都知道是有动态性的,你能通过Runtime 的API获取你想要的属性方法等等,那Swift呢?是不是也和OC一样呢?
Mr.RisingSun
2022/11/28
1.1K0
Swift-Runtime总结
swift4.0语法杂记(精简版)
一、swift简史 1、介绍 swift是苹果公司于2014年推出用于撰写OS和iOS应用程序的语言。它由苹果开发者工具部门总监“克里斯.拉特纳”在2010年开始着手设计,历时一年完成基本的架构。到后来苹果公司大力投入swift语言的研发,于2014年发布这一语言的第一版本。swift2.0之后的语法则趋于稳定,2017年发布的swift4.0虽有改动,但也只是增添了一些新特性。这些新特性需要在Xcode9上运行才能显示出效果。值得一提的是它支持unicode9,也就是说,可以用某些图片图标来充当变量。
谦谦君子修罗刀
2018/05/02
16.1K0
swift4.0语法杂记(精简版)
iOS小技能:动态地给类添加新的方法、实例变量、属性。
动态创建属性的应用场景:利用属性进行传值的时候,我们就可以利用本文的方法进行动态创建属性。尤其在逆向其他app的时候,往已经存在class新增一个属性,用于数据传递,尤其是异步操作的时候。
公众号iOS逆向
2022/08/22
2K0
iOS小技能:动态地给类添加新的方法、实例变量、属性。
Runtime系列(二)--Runtime的使用场景
Runtime 理解介绍的文章非常多,我只想讲讲Runtime 可以用在哪里,而我在项目里哪些地方用到了runtime。多以实际使用过程为主,来介绍runtime的使用。
Haley_Wong
2018/08/22
1.7K1
Runtime系列(二)--Runtime的使用场景
Objective-C Runtime:深入理解成员变量与属性
在上篇文章Objective-C Runtime:深入理解类与对象中,讲解了类与对象的相关内容。
Jacklin999
2018/09/12
8350
推荐阅读
相关推荐
对象、消息、运行期--10:runtime关联对象
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验