category添加属性

面试题

  1. Category的实现原理,以及Category为什么只能加方法不能加属性。
  2. Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗?
  3. load、initialize的区别,以及它们在category重写的时候的调用的次序。

官方文档

You use categories to define additional methods of an existing class—even one whose source code is unavailable to you—without subclassing. You typically use a category to add methods to an existing class, such as one defined in the Cocoa frameworks. The added methods are inherited by subclasses and are indistinguishable at runtime from the original methods of the class. You can also use categories of your own classes to:
1.Distribute the implementation of your own classes into separate source files—for example, you could group the methods of a large class into several categories and put each category in a different file.
2.Declare private methods.
You add methods to a class by declaring them in an interface file under a category name and defining them in an implementation file under the same name. The category name indicates that the methods are an extension to a class declared elsewhere, not a new class.

翻译:

您可以使用类别定义现有类的附加方法,即使是没有子类的源代码不可用的方法。通常使用类别向现有类添加方法,例如在COCOA框架中定义的类。添加的方法由子类继承,并且在运行时与类的原始方法不可区分您还可以使用自己类的类别来:

  1. 将自己类的实现分发到单独的源文件中例如,可以将一个大型类的方法分组到多个类别中,并将每个类别放入不同的文件中。

  2. 声明私有方法。

通过在接口文件中以类别名称声明方法并在实现文件中以相同名称定义方法,可以将方法添加到类中。类别名称表示这些方法是在别处声明的类的扩展,而不是新类。 更多内容请查看category的官方文档说明

实现分类

新建一个person类 添加属性name

    //Person.h
@interface Person : NSObject
@property (nonatomic , strong) NSString * name;
@end
//Person.m
@implementation Person @end

建立一个person + test 分类,声明一个age属性

    @interface Person (test)
@property (nonatomic , assign) int age;
@end

创建两个实例化对象来验证分类属性age是否可用

    Person *person1 = [[Person alloc]init];
person1.name = @"person1";
person1.age = 10; Person *person2 = [[Person alloc]init];
person2.name = @"person2";
person2.age = 60; NSLog(@"person1的name:%@ age:%d",person1.name,person1.age);
NSLog(@"person2的name:%@ age:%d",person2.name,person2.age);

做到这一步时候可以运行下看到-[Person setAge:]: unrecognized selector sent to instance 0x600000db88d0的错误提醒。说明我们person+test里的age并没有真正生成,或者说是和原类person里的name属性不一致。我们知道在原类声明name 其实就是系统帮我们生成了属性声明,setter和getter方法。所以我们在分类的属性声明里,自己添加分类属性的这三种方法来试试看能不能生效。

    #import "Person.h"
@interface Person()
{
NSString *_name;
}
@end
@implementation Person
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
@end
    #import "Person+test.h"
static NSInteger age1 = 0;
@implementation Person (test)
- (void)setAge:(NSInteger)age{
age1 = age;
}
- (NSInteger)age{
return age1;
}
@end

打印信息

    person1的name:person1 age:60
person2的name:person2 age:60

打印信息可以看到age的值只存了一个最后一个。无法保留原先的值,所以这种方式占用的同一块内存空间。 以上就是说明分类不能直接添加属性,接下来就讲讲分类添加属性的四种方式。

分类添加属性的四种方式

第一种:(不推荐,只是实现效果)

通过字典来存储变量,每个值一对一存储在字典里,通过self对象来做为key 真正的值作为value 弊端:字典需要一直存在,每添加一个属性,字典都会不断的扩容,分类的字典是在load方法里创建。

#import "Person+test.h"
static NSMutableDictionary *dict;
@implementation Person (test)
+(void)load{
dict = [NSMutableDictionary dictionary];
}
- (void)setAge:(NSInteger)age{
[dict setObject:[NSString stringWithFormat:@"%ld",age] forKey:[NSString stringWithFormat:@"%@",self]];
}
- (NSInteger)age{ return [[dict objectForKey:[NSString stringWithFormat:@"%@",self]] integerValue];
}
@end

第二种:(常用)

#import "Person+test.h"
#import <objc/runtime.h>
static NSString * agekey = @"agekey";
@implementation Person (test) - (void)setAge:(NSInteger)age{
objc_setAssociatedObject(self, &agekey, @(age), OBJC_ASSOCIATION_ASSIGN);
}
- (NSInteger)age{ return [objc_getAssociatedObject(self, &agekey) integerValue];
} @end

第三种:(常用)

#import "Person+test.h"
#import <objc/runtime.h>
@implementation Person (test)
- (void)setAge:(NSInteger)age{
objc_setAssociatedObject(self, &("age"), @(age), OBJC_ASSOCIATION_ASSIGN);
}
- (NSInteger)age{ return [objc_getAssociatedObject(self, &("age")) integerValue];
}
@end

第四种:(极力推荐)

推荐原因:所有方法都有系统方法提示,不会出现setter/getter存储ID不一致问题。手打字符串容易出问题。

#import "Person+test.h"
#import <objc/runtime.h>
@implementation Person (test)
- (void)setAge:(NSInteger)age{
objc_setAssociatedObject(self, @selector(age), @(age), OBJC_ASSOCIATION_ASSIGN);
}
- (NSInteger)age{ return [objc_getAssociatedObject(self, _cmd) integerValue];
}
@end

category添加属性的更多相关文章

  1. iOS Category 添加属性实现原理 - 关联对象

    iOS Category 添加属性实现原理 - 关联对象 RunTime为Category动态关联对象 使用RunTime给系统的类添加属性,首先需要了解对象与属性的关系.对象一开始初始化的时候其属性 ...

  2. 【原】iOS动态性(一):动态添加属性的方法——关联(e.g. 向Category添加属性)

    想到要如何为所有的对象增加实例变量吗?我们知道,使用Category可以很方便地为现有的类增加方法,但却无法直接增加实例变量.不过从Mac OS X v10.6开始,系统提供了Associative ...

  3. iOS动态性:动态添加属性的方法——关联(e.g. 向Category添加属性)

    想到要如何为所有的对象增加实例变量吗?我们知道,使用Category可以很方便地为现有的类增加方法,但却无法直接增加实例变量.不过从Mac OS X v10.6开始,系统提供了Associative ...

  4. iOS之Category关联属性

    Objective-C /** 原文件 */ // Person.h #import <Foundation/Foundation.h> @interface Person : NSObj ...

  5. 给category添加基本数据类型属性

    给category添加基本数据类型属性 说明 通常,我们添加属性都是通过对象扩展来实现的,其实,我们也可以用runtime来添加基本数据类型的属性 源码 // // UIView+AnimationP ...

  6. category中添加属性的简单方式

    一.概念扩充: 1.如我们所知,使用category是用来对现有类进行功能扩展,或者将类分成多模块的一种方式.由声明和实现两部分组成.可以单独写成Objiective-C File类型文件(包含.h和 ...

  7. iOS的Runtime机制下给类别(category)添加属性、替换原有类的方法执行

    一.Runtime的理解 OC是面向对象的语言这是常识,其实就是通过Runtime机制动态创建类和对象,这里只是简单的运用runtime的使用! 二.类别(category)添加属性_使用前记得导入头 ...

  8. 给分类(Category)添加属性

    遇到一个问题,写了一个分类,但原先类的属性不够用.添加一个属性,调用的时候崩溃了,说是找不到getter.setter方法.查了下文档发现,OC的分类允许给分类添加属性,但不会自动生成getter.s ...

  9. category类别中添加属性

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0. ...

随机推荐

  1. AngularJS 官方启动文档

    参考:https://angular.io/guide/quickstart 中文:http://www.angularjs.net.cn/

  2. 关于2017届学长制作分享软件share(失物招领)的使用体验和需改进的内容

    使用体验 1.注册界面 注册界面提示明显,提示用户输入什么类型的密码,而且输入什么样的用户名不限,注册界面色调比较单一,注册内容比较少,而且比较简单,体验感比较好,但注册界面色调和设计全无,使用感一般 ...

  3. 解题报告:luogu P1516 青蛙的约会

    题目链接:P1516 青蛙的约会 考察拓欧与推式子\(qwq\). 题意翻译? 求满足 \[\begin{cases}md+x\equiv t\pmod{l}\\nd+y\equiv t\pmod{l ...

  4. Docker 镜像文件的导入和导出

    使用save命令 保存镜像 docker save -o name_by_you.tar exist_images 将文件copy到另一台机器 使用load命令将镜像文件保存到本地仓库 docker ...

  5. C++ 类 与 static

    背景 从学习C++到使用现在,发现很多新的东西,正好整理一下. static 为静态,指是当类编译加载的时候,内存就会开辟存储空间的. static 数据成员 在类中,static 可修饰 类中的成员 ...

  6. POJ 3349:Snowflake Snow Snowflakes 六片雪花找相同的 哈希

    Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 35642   Accep ...

  7. GNS3 模拟icmp重定向

    网关实质上是一个网络通向其他网络的IP地址.比如有网络A和网络B,网络A的IP地址范围为“192.168.1.1~192. 168.1.254”,子网掩码为255.255.255.0:网络B的IP地址 ...

  8. SQL创建表格——手写代码

    打开phpstudy,打开Navicat for MySQL,进入要创建表格的数据库,点击上方“查询”按钮,“创建查询”,即可输入代码进行创建. 例: create table class( clas ...

  9. 无法识别的配置节 system.webServer

    Web.config文件里面加入 <configSections> <section name="system.webServer" type="Sys ...

  10. H5端js实现图片放大查看-插件photoswipe的使用

    这个是一个不知道什么鬼的东西,按照他需求改的,我也不知道对不对...看介绍说是h5把,我这个是用那个插件photoswipe的实现的 demo包地址: https://files-cdn.cnblog ...