介绍@dynamic的用法

2023-05-16

介绍@dynamic的用法

 

    Objective-C 2.0提供了属性(@property),可以让编译器自动生成setter和getter方法。如果不想编译器自作主张生成这些setter和getter方法,则使用@dynamic。举个简单例子,如下

#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (copy) NSString *name;
@end

@implementation Person
// @dynamic tells compiler don't generate setter and getter automatically
@dynamic name;
@end

int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    Person *a = [[Person alloc] init];
    
    a.name = @"Hello"; // will crash here
    NSLog(@"%@", a.name);
    
    [a release];
    [pool drain];
    
    return 0;
} // main

    运行该程序,Xcode会报错“-[PersonsetName:]: unrecognized selector sent to instance 0x1001149d0”。如果将@dynamic注释掉,则一切Ok。

    这里由于使用@dynamic,我们需要自己提供setter和getter方法。一般有两种方法:1)自己提供setter和getter方法,将编译器自动生成的setter和getter方法手动再写一遍;2)动态方法决议(DynamicMethod Resolution),在运行时提供setter和getter对应实现的C函数。

    对于第一种方法,需要在类中显式提供实例变量,因为@dynamic不能像@synthesize那样向实现文件(.m)提供实例变量。

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    // must provide a ivar for our setter and getter
    NSString *_name;
}
@property (copy) NSString *name;
@end

@implementation Person
// @dynamic tells compiler don't generate setter and getter automatically
@dynamic name;

// We provide setter and getter here
- (void) setName:(NSString *)name
{
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}

- (NSString *) name
{
    return _name;
}
@end // Person

int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    Person *a = [[Person alloc] init];
    
    a.name = @"Hello"; // Ok, use our setter
    a.name = @"Hello, world";
    NSLog(@"%@", a.name); // Ok, use our getter
    
    [a release];
    [pool drain];
    
    return 0;
} // main

    对于第二种方法,在运行时决定setter和getter对应实现的C函数,使用了NSObject提供的resolveInstanceMethod:方法。在C函数中不能直接使用实例变量,需要将ObjC对象self转成C中的结构体,因此在Person类同样需要显式声明实例变量而且访问级别是@public,为了隐藏该实例变量,将声明放在扩展(extension)中

#import <Foundation/Foundation.h>
#import <objc/objc-runtime.h> // for class_addMethod()

// ------------------------------------------------------
// A .h file
@interface Person : NSObject
@property (copy) NSString *name;
- (void) hello;
@end

// ------------------------------------------------------
// A .m file
// Use extension to override the access level of _name ivar
@interface Person ()
{
@public
    NSString *_name;
}
@end

@implementation Person
// @dynamic implies compiler to look for setName: and name method in runtime
@dynamic name;

// Only resolve unrecognized methods, and only load methods dynamically once
+ (BOOL) resolveInstanceMethod:(SEL)sel
{
    // Capture setName: and name method
    if (sel == @selector(setName:)) {
        class_addMethod([self class], sel, (IMP)setName, "v@:@");
        return YES;
    }
    else if (sel == @selector(name)) {
        class_addMethod([self class], sel, (IMP)getName, "@@:");
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}

void setName(id self, SEL _cmd, NSString* name)
{
    // Implement @property (copy)
    if (((Person *)self)->_name != name) {
        [((Person *)self)->_name release];
        ((Person *)self)->_name = [name copy];
    }
}

NSString* getName(id self, SEL _cmd)
{
    return ((Person *)self)->_name;
}

- (void) hello
{
    NSLog(@"Hello, world");
}

@end // Person

int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    Person *a = [[Person alloc] init];
    [a hello]; // never call resolveInstanceMethod
    
    a.name = @"hello1";
    NSLog(@"%@", a.name);
    a.name = @"hello2";
    NSLog(@"%@", a.name);
    
    [a release];
    [pool drain];
    
    return 0;
} // main


    总结以上,@dynamic的作用就是禁止编译器为@property产生setter和getter方法,有两种办法实现setter和getter方法:1)自己提供setter和getter方法;2)方法动态决议(DynamicMethod Resolution)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

介绍@dynamic的用法 的相关文章

  • 如何根据 iPhone 中的文本大小动态增加按钮宽度?

    我以编程方式创建了 10 个按钮 并在按钮中设置了标题 现在我想动态增加按钮框架大小 它取决于文本 我给出了一些条件并设置了框架大小 但我如何设置确切的帧大小取决于文本 动态获取文本 我的示例代码是 float x 0 y 0 w h 20
  • 是否可以查询ExpandoObject列表?

    我想知道是否可以使用常规 LINQ 查询 ExpandoObject 原因是我有动态 ExpandoObject 但我需要进行一些查询才能进一步传递 它有一些始终保留的属性 例如Id Notes还有一些我无法控制的动态属性 这是我的列表的样
  • 声明后在 C++ 向量中分配元素

    请参考下面的代码和注释 vector
  • 保留时间值的动态 PL/SQL 日期参数

    这可能是一个愚蠢的问题 但我找不到在动态调用的 PL SQL 过程中传递 DATE 类型的解决方案 我需要的是在被调用的过程中传递日期和时间部分 create or replace PROCEDURE DATE TIME TEST dte
  • 有没有简单的方法可以在 C# 中创建方法并动态设置其主体?

    我将方法体保存在字符串中 我想动态创建方法 但我不知道 如何设置它的身体 我看到使用 CodeDom 的方式非常乏味 我看到使用 Emit 和操作码 有什么方法可以使用字符串变量中的现成代码吗 string method body retu
  • 动态 SQL 示例

    我最近了解了什么是动态 sql 它对我来说最有趣的功能之一是我们可以使用动态列名和表 但我无法思考现实生活中有用的例子 我唯一想到的是统计表 假设我们有一个包含名称 类型和created data 的表 然后我们想要一个表 其列中是从cre
  • C++ 释放结构体使用的所有内存

    快速提问 我已经用谷歌搜索并找到了一些答案 但我有点偏执 所以我想确定一下 考虑这种情况 struct CoordLocation float X float Y float Z int main CoordLocation coord n
  • 动态对象创建

    我有一个接受字符串对象名称的函数 我需要该函数来创建与字符串值同名的对象的新实例 例如 function Foo function create name return new name create Foo should be equiv
  • 反思 ExpandoObject

    我写了一个漂亮的函数 它将接受system object 反映其属性并将对象序列化为 JSON 字符串 它看起来像这样 public class JSONSerializer public string Serialize object o
  • Android UI - 动态添加按钮到 Gridview

    这就是我现在陷入困境的地方 我一直坚持向 gridview 动态添加按钮 我的 gridview 带有一个按钮 当用户单击该按钮时 会弹出上下文菜单 要求用户输入信息 完成后 使用该信息创建网格视图中的块 如图所示 我已经粘贴了代码 我不知
  • 使用 jQuery 动态填写表单值

    我知道如何使用纯 PHP 执行此操作 但我需要在不重新加载页面的情况下执行此操作 无论如何 jQuery 是否可以有效地拉回一些数据库结果 基于用户在表单上的第一个文本字段中输入的内容 然后使用从数据库查询拉回的数据填充剩余的一些字段 本质
  • 如何动态创建 C# 面板

    我创建了一个联系人管理器 用户已经可以输入一些内容并将它们存储在文件中并在程序启动时重新打开 每个联系人都是我的 Person 类的一个对象 启动程序时 在 Load 中 我创建了一个 for 循环 直到探索完所有联系人 在 Person
  • Zurb Foundation:如何在调整大小到较小的屏幕时使按钮变小?

    在 Zurb Foundation 4 中 是否有一种方法可以在浏览器尺寸调整得较小或在较小的屏幕上时自动切换到较小的按钮样式 例如 当屏幕是标准桌面屏幕时 请执行以下操作 a href class primary button Butto
  • 如何检查 C# 中动态匿名类型上是否存在属性?

    我有一个匿名类型对象 我从方法中以动态方式接收该对象 我想检查该对象上是否存在属性 var settings new Filename temp txt Size 10 function void Settings dynamic sett
  • 在 C# winforms 的控件内水平和垂直对齐动态添加的控件

    我有这个程序 可以动态添加引用数据库中总统号码的图片框 如何将它们放入组框内并对齐组框内的图片框 如果图片框很多 则组框应该拉伸 我现在有这个代码 private void Form1 Load object sender EventArg
  • 如何动态更改字体名称?

    我正在使用 Jasper jar 生成有关我的 J2EE 项目的报告 我能够成功生成 PDF 没有任何问题 但是 我希望根据我们在一处配置的设置动态更改所有 PDF 的字体名称 我开始了解条件样式 这对于完成此任务很有用 然而 我确实有数百
  • 动态框架中未定义的架构符号

    我正在开发一个 iOS 框架 该框架包含多个第三方框架并使用 UnitySendMessage C 方法与 Unity 进行通信 我想创建一个动态框架 支持 iOS8 但我偶然发现以下编译错误 Undefined symbols for a
  • C# WPF 如何动态设置属性设置方法?

    我一直在四处寻找 但似乎找不到我要找的东西 所以我会在这里尝试一下 情况 我有 MainWindow 和 MainWindowData 类 MainWindowData 中只有使用 UpdateGUI 属性定义的公共属性 public cl
  • 如何从网站中抓取动态内容?

    所以我使用 scrapy 从亚马逊图书部分抓取数据 但不知何故我知道它有一些动态数据 我想知道如何从网站中提取动态数据 到目前为止我已经尝试过以下方法 import scrapy from items import AmazonsItem
  • 如何在.NET 3.5中进行动态对象创建和方法调用

    创建类对象的代码看起来如何 string myClass MyClass 上面的类型 然后调用 string myMethod MyMethod 在那个物体上 Use Type GetType string http msdn micros

随机推荐

  • JLINK简介

    一 什么是JLINK JLINK是一个兼容JTAG的仿真器 xff0c 作用是烧入程序和Debug 二 JLINK是如何处理数据的 xff1f 1 PC端应用程序将数据以某种协议格式 xff0c 通过USB接口发送给J Link 2 J L
  • 蓝桥杯单片机-DS1302时钟模块

    一 简介 1 采用SPI三线接口通信 xff08 SCK SDA RST xff09 上升沿数据被写入DS1302 xff0c 下降沿被读出 二 应用 1 在ds1302 c文件中定义三个数组 unsigned char code READ
  • 蓝桥杯单片机-定时器

    一 简介 有三个寄存器与定时器相关 xff08 TMOD xff0c TCON xff0c 数值设置寄存器TH TL xff09 1 定时器工作方式设置寄存器TMOD GATE 门控制位 GATE 61 0时 定时器 计数器启动与停止仅受T
  • 蓝桥杯单片机-NE555模块

    一 简介 1 NE555在开发板中用于输出频率可变 xff0c 占空比不变的方波 2 NE555是纯硬件的设计 xff0c 通过电位器RB3可改变其信号输出频率 不需要编程实现其功能 考点 xff1a 使用定时器的计数模式测量NE555输出
  • C语言学习笔记(基于单片机)

    目录 一 关键字部分 static code const extern bit sbit sft struct xff08 结构体 xff09 1 结构体的初始化 2 结构体的赋值 3 应用 data idata pdata xdata 与
  • 蓝桥杯单片机-赛前总结

    目录 一 省赛中开发平台涉及的模块 xff1a 1 IIC驱动 2 DS1302驱动 3 onewire驱动 4 定时器读取NE555频率 二 一些功能性操作 1 外部中断 2 矩阵按键 3 PWM输出 4 毫秒延时函数 三 需要注意的一些
  • 相互依赖的so库,在编译时如何解耦

    有时候 xff0c 我们写的程序 xff0c 会涉及到相互引用的问题 比如frameworks av media libstagefright下的这个libstagefright xff0c 被frameworks av media lib
  • boost库学习总结

    第一次使用boost库是因为网络编程 xff0c 由于时间比较紧 xff0c 没有时间每个库都学 xff0c 所以前期想找个专门的boost库网络教程 xff08 以前自己就用过socket写过 xff0c 但是为了跨平台 xff0c 而且
  • C51单片机判断点亮的是奇数位还是偶数位

    学单片机的时候想到一个问题 xff1a 如何判断单片机点亮的LED灯是奇数位还是偶数位 xff1f 在网上搜了一圈没找到 xff0c 于是打算自己写一个 单片机型号 xff1a AT89C52 xff0c LED为低电平有效接法 xff0c
  • Linux学习笔记——如何在交叉编译时使用共享库

    0 前言 在较为复杂的项目中会利用到交叉编译得到的共享库 xff08 so文件 xff09 在这种情况下便会产生以下疑问 xff0c 例如 xff1a 1 交叉编译时的共享库是否需要放置于目标板中 xff0c 如果需要放置在哪个目录中 2
  • 实例变量(instance var)与属性(@property)的关系

    实例变量 instance var 与属性 64 property 的关系 Objective C 2 0之后 xff0c 声明一个 64 property name自动产生一个实例变量 xff0c 名为 name xff0c 因此省去实例
  • VS+CUDA+Matlab环境配置经验 (达到用matlab使用nvcc进行gpu并行加速)

    前前后后配了一个多星期的环境 xff0c 终于完成了 xff0c 梳理一下我的经验给大家分享也留作以后参考 一 版本兼容性问题 一开始安装的时候我并不懂 xff0c 没有什么顺序和版本的概念 xff0c 所以各种组件不能相互支持 首先明确
  • 华为无线WiFi配置802.1x认证

    一 拓扑 xff1a 二 简介 xff1a 本篇主要介绍华为交换机设备配合Windows server 2019配置的802 1x 43 NPS协同做的有线网络认证 xff08 可跟做 xff09 现有的华为6605无线AC配置 xff1a
  • 寝室一伙计

    我们寝室一伙计 xff0c 昨天晚上睡觉的时候 xff0c 说梦话 xff0c 笑 xff0c 磨牙 xff0c 还有吃奶 xff0c 等等等等 xff0c 我服了
  • Qt学习笔记(五)重定向

    实时获取程序中qt所输出的信息 xff0c 并显示到QTextBrowser上 1 在main文件中添加以下内容 xx为你的界面类名 xx clk 61 NULL void myMessageOutput QtMsgType type co
  • 串口通信中接收数据时延迟处理与缓存处理的解决方案(C#)

    利用串口进行通信 xff0c 当发送方 xff08 A xff09 将数据写入串口后 xff0c 通过无线或有线方式将数据传送给接收方 xff08 B xff09 xff0c B通过调用串口读方法comm read 参数 即可将数据读出 原
  • robomaster电控究极学习教程(以哨兵为例)------一、串口dma和遥控器

    robomaster电控究极学习教程 xff08 以哨兵为例 xff09 一 串口dma和遥控器 文章目录 robomaster电控究极学习教程 xff08 以哨兵为例 xff09 一 串口dma和遥控器 一 串口DMA的作用二 步骤1 c
  • 无人机架构

    无人机架构 基本设计需求 xff0c 如 xff1a xff08 1 xff09 慎思规划和反应式行为 xff1b xff08 2 xff09 容许不确定性 xff1b xff08 3 xff09 考虑危险 xff1b xff08 4 xf
  • 第八课 C++中的__LINE__宏

    在C 43 43 编程中 xff0c 我们有时候需要知道当前源代码的行号 xff0c 这时候就可以使用 LINE 宏 本文将介绍如何使用 LINE 宏 xff0c 以及它的使用示例 LINE 宏简介 LINE 是C 43 43 中的一个预定
  • 介绍@dynamic的用法

    介绍 64 dynamic的用法 Objective C 2 0提供了属性 64 property xff0c 可以让编译器自动生成setter和getter方法 如果不想编译器自作主张生成这些setter和getter方法 xff0c 则