文档章节

iOS分类不能添加属性原因的探索

hanbing94
 hanbing94
发布于 2017/05/08 12:18
字数 949
阅读 6
收藏 0
点赞 0
评论 0

最近跟人交流时,提到一个问题,说iOS分类中不能添加属性。这里探讨一下不能添加的原因和添加的方法。
首先,创建一个person类,代码如下:

XGPerson.h

#import <Foundation/Foundation.h>

@interface XGPerson : NSObject
/// 年龄
@property (nonatomic, copy) NSString *age;
/// 性别
@property (nonatomic, copy) NSString *sex;

- (void)text1;

@end

XGPerson.m

#import "XGPerson.h"

@implementation XGPerson

- (void)text1 {
    NSLog(@"%s",__func__);
}

- (void)text2 {
    NSLog(@"%s",__func__);
}
@end

在控制器里获取并打印该类的成员变量、属性和方法,代码如下:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取成员变量
    unsigned int ivarCount = 0;
    Ivar *ivars = class_copyIvarList([XGPerson class], &ivarCount);
    for (int i = 0; i < ivarCount; i++) {
        Ivar ivar = ivars[i];
        NSLog(@"第%d个成员变量:%s",i,ivar_getName(ivar));
    }
    free(ivars);
    // 获取属性
    unsigned int propertyCount = 0;
    objc_property_t *propertyList = class_copyPropertyList([XGPerson class], &propertyCount);
    for (int i = 0; i < propertyCount; i++) {
        objc_property_t property = propertyList[i];
        NSLog(@"第%d个属性:%s",i,property_getName(property));
    }


    // 获取方法列表
    unsigned int methodCount = 0;
    Method *methods = class_copyMethodList([XGPerson class], &methodCount);
    for (int i = 0; i < methodCount; i++) {
        Method method = methods[i];

        NSLog(@"第%d个方法:%s",i, sel_getName(method_getName(method)));
    }

}

此时控制台输出如下:

没有分类时.png


这里需要提出的是,平时使用@property的时候,系统会自动生成带“_”的成员变量和该变量的setter和getter方法。也就是说,属性相当于一个成员变量加getter和setter方法。那么,在分类里使用@property会是什么样子呢,下面来创建一个分类:
XGPerson+height.h

#import "XGPerson.h"

@interface XGPerson (height)

@property (nonatomic, copy) NSString *height;

@end

XGPerson+height.m

#import "XGPerson+height.h"

#import <objc/runtime.h>

@implementation XGPerson (height)


@end

如果像上面一样只在.h文件里声明height,那么.m文件里会出现两个警告,意思是说没有实现setter和getter方法。

警告.png

此时在控制器里执行touchesBegan方法,控制台输出如下:

有分类未实现存取方法.png


可以看到,此时person类里并没有添加带“_”的成员变量,也没有实现setter和getter方法,只是在属性列表里添加了height属性。并且此时如果在控制器里调用self.height,程序运行时会报错,显示找不到该方法。实现一下person分类里的两个方法:
XGPerson+height.m

#import "XGPerson+height.h"

#import <objc/runtime.h>

@implementation XGPerson (height)

 - (NSString *)height {

 }

 - (void)setHeight:(NSString *)height {

 }

@end

此时在控制器里执行touchesBegan方法,控制台输出如下:

有分类实现存取方法.png

可以看到即使实现了setter和getter方法,也仍然没有添加带“”的成员变量,也就是说,在setter和getter方法里仍然不能直接访问以下划线开头的成员变量,因为在分类里用@property声明属性时系统并没有添加以“”开头的成员变量。此时要达到添加的目的可以使用运行时的关联对象。示例代码如下:
XGPerson+height.m

#import "XGPerson+height.h"

#import <objc/runtime.h>

@implementation XGPerson (height)



 - (NSString *)height {
 return objc_getAssociatedObject(self, @"height");
 }


 - (void)setHeight:(NSString *)height {
 objc_setAssociatedObject(self, @"height", height, OBJC_ASSOCIATION_COPY_NONATOMIC);
 }

@end

当然也可以在setter和getter方法里访问该类其他的属性,比如在UIView的分类的里添加x、y属性,可以直接返回self.frame.origin.x和self.frame.origin.y。

总结

在分类里使用@property声明属性,只是将该属性添加到该类的属性列表,并声明了setter和getter方法,但是没有生成相应的成员变量,也没有实现setter和getter方法。所以说分类不能添加属性。但是在分类里使用@property声明属性后,又实现了setter和getter方法,那么在这个类以外可以正常通过点语法给该属性赋值和取值。就是说,在分类里使用@property声明属性,又实现了setter和getter方法后,可以认为给这个类添加上了属性。

本文转载自:

共有 人打赏支持
hanbing94
粉丝 2
博文 66
码字总数 38602
作品 0
朝阳
iOS查看屏幕帧数工具--YYFPSLabel

学习 YYKit 代码时,发现 ibireme 在项目里加入的一个查看当前屏幕帧数的小工具,效果如下: 挺实用,实现方法也很简单,但是思路特别棒。 这里是Demo: YYFPSLabel 这里我把这个小工具从 中...

yehot ⋅ 2016/04/05 ⋅ 0

说说 NSTimer 的新 API

本文是我首发在iOS知识小集团队的,欢迎关注微博话题#ios知识小集#。 在以往的 iOS 版本中,我们为了避免 NSTimer 的循环引用问题,一个比较常用的解决办法是为 NSTimer 添加一个 category,...

halohily ⋅ 05/03 ⋅ 0

iOS自定义弹出视图、收音机APP、图片涂鸦、加载刷新、文件缓存等源码

iOS精选源码 一款优秀的 聆听夜空FM 源码(http://www.code4app.com/thread-14546-1-1.html) zhPopupController 简单快捷弹出自定义视图(http://www.code4app.com/thread-14861-1-1.html) WHS......

sunnyaigd ⋅ 06/04 ⋅ 0

你见过最目瞪狗呆的bug是什么?

你见过最目瞪狗呆的bug是什么? 2018-05-28 14:01编辑: garace分类:程序人生来源:代码湾 bug网上注册刘伟楠 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发工程师 京东招聘iOS开发...

garace ⋅ 05/28 ⋅ 0

【AR】开始使用Vuforia开发iOS(2)

原 设置iOS开发环境 安装Vuforia iOS SDK 如何安装Vuforia iOS示例 编译并运行Vuforia iOS示例 支持iOS金属 iOS 64位迁移 设置iOS开发环境 适用于iOS的Vuforia引擎目前支持运行iOS 9及更高版...

lichong951 ⋅ 06/11 ⋅ 0

常见的移动端H5页面开发遇到的坑和解决办法

手机共通问题 问题一:用同等比例的图片在PC机上很清楚,但是手机上很模糊,原因是什么呢? 经研究发现是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率来显示网页字会非常小,所以苹果...

webmirror ⋅ 05/02 ⋅ 0

iOS天气动画、高仿QQ菜单、放京东APP、高仿微信、推送消息等源码

iOS精选源码 TYCyclePagerView iOS上的一个无限循环轮播图组件(http://www.code4app.com/thread-14507-1-1.html) iOS高仿微信完整项目源码(http://www.code4app.com/thread-14695-1-1.html)......

sunnyaigd ⋅ 06/12 ⋅ 0

iOS一些代码的取巧写法总结(一)

一、 字典(NSDictionary)和JSON字符串(NSString)之间互转 二、打开摄像机作为背景 三、打开背光灯 四、状态栏和导航栏一些设置 五、切回app时、会有闪现、闪现一次主屏幕的现象 六、[UIAppl...

朝雨晚风 ⋅ 2016/12/05 ⋅ 0

Windows 95 风格的 iOS UI 组件集 - ClassicKit

ClassicKit 是一个适用于 iOS 的 Windows 95 经典风格 UI 组件集。 ClassicKit 将 Windows 95 的风格带入了 iOS 应用中,大部分图标等资源都来自实际安装的 Windows 95,效果感觉就像在 iOS ...

匿名 ⋅ 05/17 ⋅ 0

又拍云Prism CDN 超低价 低延时 超强兼容的P2P-CDN

又拍云Prism CDN 超低价 低延时 超强兼容的P2P-CDN 2018-05-15 10:26编辑: 枣泥布丁分类:业界动态来源:https://www.upyun.com/products CDN又拍云 招聘信息: C++工程师 Cocos2d-x游戏客户...

枣泥布丁 ⋅ 05/15 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java集合类总结笔记

一、集合类的层次关系 主要容器集合类的特点: ArrayList 一种可以动态增长和缩减的索引序列 LinkedList 一种可以在任何位置进行高效地插入和删除的有序序列 ArrayDeque 一种用循环数组实现的...

edwardGe ⋅ 2分钟前 ⋅ 0

spring RMI远程调用

RMI https://www.cnblogs.com/wdh1995/p/6792407.html

BobwithB ⋅ 8分钟前 ⋅ 0

Jenkins实践2 之基本配置

1 插件管理 系统管理->插件管理 在可选插件中可以自主安装插件 2 管理用户 系统管理->管理用户->新建用户 3 安全配置 系统管理->全局安全配置 授权策略 选择安全矩阵 然后添加现有的用户,赋...

晨猫 ⋅ 8分钟前 ⋅ 0

c++智能指针

1、是一种泛型类,针对指针类型的泛型类,会保存指针 2、重载了符号 *和-> 对智能指针使用这两个符号,相当于对保存的泛型使用这两个符号 3、当智能指针引用计数为0时,会去释放指针指向的资...

国仔饼 ⋅ 9分钟前 ⋅ 0

Spring Boot错误处理机制

1)、SpringBoot默认的错误处理机制 默认效果: 1)、浏览器,返回一个默认的错误页面 浏览器发送请求的请求头: 2)、如果是其他客户端,默认响应一个json数据 原理: 可以参照ErrorMvcAut...

小致dad ⋅ 10分钟前 ⋅ 0

ftp连接不上的终极办法 SFTP

假如FTP由于各种原因就是连不上,那么用SFTP协议吧,使用登录服务器的账号密码。

sskill ⋅ 15分钟前 ⋅ 0

Unity 围绕旋转角度限制(Transform.RotateAround)

在 Unity 中可以利用 Transform.RotateAround 围绕指定物体进行旋转,但某些情况下可能需要对旋转角度进行控制。我是先计算出预设角度大小,然后判断是否在限定角度范围内是则进行旋转。 相关...

大轩 ⋅ 15分钟前 ⋅ 0

阿里沙箱环境支付宝测试demo

阿里支付宝支付和微信支付,包括:阿里沙箱环境支付宝测试demo,支付宝支付整合到spring+springmvc+mybatis环境和微信整合到如上环境,功能非常齐全,只需要修改对应的配置文件即可,帮助文档...

码代码的小司机 ⋅ 18分钟前 ⋅ 0

JDK1.6和JDK1.7中,Collections.sort的区别,

背景 最近,项目正在集成测试阶段,项目在服务器上运行了一段时间,点击表格的列进行排序的时候,有的列排序正常,有的列在排序的时候,在后台会抛出如下异常,查询到不到数据,而且在另外一...

tsmyk0715 ⋅ 35分钟前 ⋅ 0

C++ 中命名空间的 5 个常见用法

相信小伙伴们对C++已经非常熟悉,但是对命名空间经常使用到的地方还不是很明白,这篇文章就针对命名空间这一块做了一个叙述。 命名空间在1995年被引入到 c++ 标准中,通常是这样定义的: 命名...

柳猫 ⋅ 40分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部