Code_浅蓝之runtime学习与记录

EVM底层探索:字节码级分析最小化代理标准EIP1167 本文主要介绍了以下内容 `openzeppelin`的`clone`函数生成字节码的过程、go-ethereum创建智能合约的源代码。除此之外,我们还介绍EVM运行环境的基本情况和常见字节码的含义。 阅读详情

iOS内功篇:runtime

iOS runtime实战应用:成员变量和属性

iOS runtime实战应用:关联对象

iOS runtime实战应用:Method Swizzling

以下属于我的摘着和学习

iOS内功篇:runtime

runtime是一个c和汇编写的动态库,它就像一个小小的系统,将OC和C紧密关联;这个系统主要做两件事

  1. 封装C语言的结构体和函数,让开发者在运行时创建、检查或修改类,对象和方法等等。
  2. 传递消息,找出方法的最终执行代码。

栗子:

[student walkTheDog];

那么runtime会将它转化成C语言的代码

objc_msgSend(student, @selector(walkTheDod));

这个方法就是发送消息的方法,类似这样的方法runtime提供了很多,比如:

// 获取属性列表
objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount ); 
// 获取所有方法的数组
Method * class_copyMethodList ( Class cls, unsigned int *outCount );    
 // 添加方法        
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types );     

那么我们可以利用这些方法干点什么?

方法调用流程

 1> 遍历对象的属性
 比如;看看student的有哪些属性(性别,生日)
 2> 动态添加/修改属性,动态添加/修改/替换方法
  比如: 修改student的性别,生日日期,walkTheDog(变成study)
 3> 动态创建Class/Object/Protocol等等...
 4> 方法拦截调用(修改实现/添加实现)
 比如:Student1发送一个walkTheDog消息, 而walkTheDog方法没有实现,我们可以通过runtime拦截,给方法动态添加一个实现,甚至可以让其他对象Student2来walkTheDog;

下面以实例对象调用 student walkTheDog 为栗子描述方法调用流程:

    1> 编译器会把`student walkTheDog` 转化为objc_msgSend(student,@seletor(walkTheDog))
    2> `runtime` 会在student实例对象所对应的Student类的方法缓存列表里查找方法SEL
    3> 如果没有找到,则在Student类的方法分发表查找方法的SEL。(类由对象isa指针指向,方法分发表即methodList)
    4> 如果没有找到,则在其父类的方法分发表里查找方法的SEL(父类由类的superClass指向 [self和super区别](http://blog.youkuaiyun.com/li15809284891/article/details/54836905)),如果一直没找到,会到达NSObject基类,最终没有改方法则编译器报错。
    5> 如果使用`student preformSelector:@selector:(walkTheDog)`的方式调用方法,需要到运行时才能确定对象能否接收指定的消息,这个时候会进入消息转发流程

消息转发流程

1> 动态方法解析
接收到位置消息时(假设student的walkTheDog方法尚未实现), runtime 会调用 +resolveInstanceMethod:(实例方法)或者+resolveClassMethod:(类方法),在该方法中,我们可以给未知消息新增一个已经实现的方法。

void study(id self, SEL _cmd) {
    //let the student study
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    NSString *selString = NSStingFormSelector(sel);
    if ([selString isEqualToString:@"walkTheDog"]){
        class_addMethod(self.class, @selector(walkTheDog), (IMP)study, "@:");
    }
    return [super resolveInstanceMethod:sel];
}

2> 备用接收者

如果以上方法都没有做处理, runtime会调用 - (id)forwardingTargetForSelector:(SEL)aSelector 方法。
如果该方法返回了一个非nil (也不是self)的对象,而且该对象实现了这个方法,那么这个对象就成了消息的接收者,消息就被分发到该对象。

适用情况: 通常在对象内部使用,让内部的另一个对象处理消息,在外面看起来就像是对象处理了消息。

-(id)forwardTargetForSelector:(SEL)aSelector {
    NSString *selString = NSStringFromSelector(aSelector);
    if ([selString isEquaToString:@"walkTheDog"])
        return self.student2;
    }
    return [super forwardingTargetSelector:aSelector];
}

3> 完整消息转发
在- (void)forwardInvocation:(NSInvocation *)anInvocation方法中选择转发消息的对象,其中anInvocation对象封装了未知消息的所有细节,并保留调用结果发送到原始调用者。
比如:student将消息完整转发brother来处理

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    if ([Person instancesRespondToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:self.person];
    }
}

4> 如果在以上三个方法都没有处理未知消息,则会引发异常。


iOS runtime实战应用:成员变量和属性


成员变量


1、定义:


Ivar: 实例变量类型,是一个指向objc_ivar结构体的指针

typedef struct objc_ivar *Ivar;

2、操作函数:


// 获取所有成员变量
class_copyIvarList
// 获取成员变量名
ivar_getName
// 获取成员变量类型编码
ivar_getTypeEncoding
// 获取指定名称的成员变量
class_getInstanceVariable
// 获取某个对象成员变量的值
object_getIvar
// 设置某个对象成员变量的值
object_setIvar

3、使用实例:


Model的头文件声明如下:

     @interface Model : NSObject {
        NSString * _str1;
     }
     @property NSString * str2;
     @property (nonatomic, copy) NSDictionary * dict1;
     @end

获取其成员变量:

     unsigned int outCount = 0;

     // 获取所有成员变量
     Ivar * ivars = class_copyIvarList([Model class], &outCount);

     for (unsigned int i = 0; i < outCount; i ++) {

        Ivar ivar = ivars[i];

        const char * name = ivar_getName(ivar);

        const char * type = ivar_getTypeEncoding(ivar);

        NSLog(@"类型为 %s 的 %s ",type, name);
    }

    free(ivars);

打印结果:

[897:26127] 类型为 @"NSString" 的 _str1 
[897:26127] 类型为 @"NSString" 的 _str2 
[897:26127] 类型为 @"NSDictionary" 的 _dict1 

属性


1、定义:

objc_property_t:声明的属性的类型,是一个指向objc_property结构体的指针

typedef struct objc_property *objc_property_t;

2、操作函数:

// 获取所有属性
class_copyPropertyList

说明:使用class_copyPropertyList并不会获取无@property声明的成员变量

// 获取属性名
property_getName
// 获取属性特性描述字符串
property_getAttributes
// 获取所有属性特性
property_copyAttributeList

说明:
property_getAttributes函数返回objc_property_attribute_t结构体列表,objc_property_attribute_t结构体包含name和value,常用的属性如下:

属性类型  name值:T  value:变化
编码类型  name值:C(copy) &(strong) W(weak) 空(assign) 等 value:无
非/原子性 name值:空(atomic) N(Nonatomic)  value:无
变量名称  name值:V  value:变化

使用property_getAttributes获得的描述是property_copyAttributeList能获取到的所有的name和value的总体描述,如 T@"NSDictionary",C,N,V_dict1

3、使用实例:

unsigned int outCount = 0;
objc_property_t *porperties = class_copyProperList([Model class], &outCount):
for (unsigned int i = 0, i<outCount; i++) {
    objc_property_t property = properties[i];
    //属性名
    const char *name = property_getName(property);
    //属性描述
    const char *propertyAttr = proper_getAttributes(property);
    NSLog(@"属性描述为 %s 的 %s", propertyAttr, name);

       //属性的特性
        unsigned int attrCount = 0;
        objc_property_attribute_t * attrs = property_copyAttributeList(property, &attrCount);
        for (unsigned int j = 0; j < attrCount; j ++) {
            objc_property_attribute_t attr = attrs[j];
            const char * name = attr.name;
            const char * value = attr.value;
            NSLog(@"属性的描述:%s 值:%s", name, value);
        }
        free(attrs);
        NSLog(@"\n");
    }
    free(properties);
}

打印结果:

text[1202:55532] 属性名: str2 属性描述: T@"NSString",&,V_str2
text[1202:55532] 属性名: T 值:@"NSString"
text[1202:55532] 属性名: & 值:
text[1202:55532] 属性名: V 值:_str2
text[1202:55532] 
text[1202:55532] 属性名: dict1 属性描述: T@"NSDictionary",C,N,V_dict1
text[1202:55532] 属性名: T 值:@"NSDictionary"
text[1202:55532] 属性名: C 值:
text[1202:55532] 属性名: N 值:
text[1202:55532] 属性名: V 值:_dict1
text[1202:55532] 

应用实例


1、简单的JSON转模型

- (instancetype)initWithDict:(NSDictionary *)dict {

    if (self = [self init]) {
        //(1)获取类的属性及属性对应的类型
        NSMutableArray * keys = [NSMutableArray array];
        NSMutableArray * attributes = [NSMutableArray array];
        /*
         * 例子
         * name = value3 attribute = T@"NSString",C,N,V_value3
         * name = value4 attribute = T^i,N,V_value4
         */
        unsigned int outCount;
        objc_property_t * properties = class_copyPropertyList([self class], &outCount);
        for (int i = 0; i < outCount; i ++) {
            objc_property_t property = properties[i];
            //通过property_getName函数获得属性的名字
            NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
            [keys addObject:propertyName];
            //通过property_getAttributes函数可以获得属性的名字和@encode编码
            NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
            [attributes addObject:propertyAttribute];
        }
        //立即释放properties指向的内存
        free(properties);

        //(2)根据类型给属性赋值
        for (NSString * key in keys) {
            if ([dict valueForKey:key] == nil) continue;
            [self setValue:[dict valueForKey:key] forKey:key];
        }
    }
    return self;

}

2、快速归档

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        unsigned int outCount;
        Ivar * ivars = class_copyIvarList([self class], &outCount);
        for (int i = 0; i < outCount; i ++) {
            Ivar ivar = ivars[i];
            NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            [self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    unsigned int outCount;
    Ivar * ivars = class_copyIvarList([self class], &outCount);
    for (int i = 0; i < outCount; i ++) {
        Ivar ivar = ivars[i];
        NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
}

3、访问私有变量

    Ivar ivar = class_getInstanceVariable([Model class], "_str1");
    NSString * str1 = object_getIvar(model, ivar);
ML工程师必备的7个Chrome生产力扩展深度指南 浏览器是机器学习工程师的第二开发环境,而Chrome扩展实质上是嵌入工作流的认知加速器。本文围绕模型发现、代码溯源、数据可视化、学术追踪等核心场景,解析如何通过轻量级、低权限、高确定性的浏览器工具,将信息获取延迟从秒级压缩至毫秒级。重点涵盖Hugging Face模型元数据解析、GitHub函数级代码导航、ArXiv语义相似推荐、Colab代码自动格式化、Plotly图表增强导出、JSON响应智能高亮及Model Card标准化解读等关键技术能力,兼顾工程稳定性与隐私安全,为数据科学家和ML工程师提供可落地 阅读详情

相关推荐

WPSJS插件开发实战:从零构建高效办公自动化工具

办公自动化是提升现代工作效率的核心技术之一,其原理在于通过编程接口实现对办公软件功能的扩展与定制。WPSJS作为一套基于JavaScript的API,为开发者提供了直接操作WPS文字、表格和演示文档的能力,其技术价值在于将Web开发的灵活性与桌面办公软件的强大文档处理能力深度融合。这使得前端开发者能够利用熟悉的HTML、CSS和JavaScript技术栈,快速构建出提升重复性文档处理效率的个性化插件。应用场景广泛覆盖了数据批量处理、报告自动生成、格式统一等日常办公痛点。本文以实战项目为例,深入解析了WPSJ

weixin_34007886的博客 433

在谈runtime

一、关于runtime 之前在项目中有遇到过用runtime解决改变全局字体的问题,所以再一次感受到了runtime黑魔法的强大,趁现在有机会分享一下对runtime的一些理解。在对象调用方法是Objective-C中经常使用的功能,也就是消息的传递,而Objective-C是C的超集,所以和C不同的是,Objective-C使用的是动态绑定,也就是runtime。Objective-C的消

code life 1157

Vega-Lite实战指南:声明式可视化的核心原理与生产落地

数据可视化正从‘画图工具’转向‘可编程契约’,Vega-Lite作为基于JSON的声明式语法,通过分离数据、编码、标记与交互逻辑,实现图表的可推导性、组合性与编译时确定性。其核心在于将可视化建模为数据流图(DAG),而非DOM操作或命令式脚本;借助transform、encoding、layer和param等原语,天然支持响应式布局、地理热力图、主从联动与零JS交互控件。技术价值体现在跨团队协作提效(产品可读spec)、CI/CD友好(JSON即配置)、嵌入式部署轻量(无运行时依赖)及长期可维护性。典型应用

weixin_33692284的博客 422

OC runtime 类与对象

struct objc_class { Class isa; //实例的isa指向类对象,类对象的isa指向元类 #if !__OBJC2__ Class super_class; //指向父类 const char *name; //类名 long version; // 类的版本信息,初始化默认为0,可以通过runtime函数cl

ios 学徒 526

置换矩阵、转置矩阵以及向量空间、子空间

置换矩阵、转置矩阵以及向量空间、子空间导读置换矩阵 导读 MIT矩阵分析课程之后的的二篇笔记。

qq_44677482的博客 1673

IEC61850客户端连接实战:CMS vs MMS协议抓包对比与性能初探(基于YX-PIS协议栈)

本文深入探讨了IEC61850客户端连接中CMS与MMS协议的抓包对比与性能优化。通过Wireshark抓包分析、协议栈配置实战和性能基准测试,揭示了两种协议在连接建立、数据交互和性能调优方面的关键差异,为智能电网自动化系统的协议选择提供了实用指南。

weixin_29209805的博客 215

【Code】Runtime Error(ACCESS_VIOLATION) 解决方法

在做题过程中,偶尔会遇到Runtime Error(ACCESS_VIOLATION) 的错误提示。 遇到这种运行错误,一般情况下是数组下标越界造成的,只需检查数组开的是否足够大,并将数组范围适当开大即可。

Ljnoit 1414

Quartus Prime器件库安装实战:从版本选择到权限避坑指南

本文详细介绍了Quartus Prime器件库的安装全流程,从版本选择、精准下载到权限设置和安装验证。重点解析了版本匹配的黄金法则、管理员权限的必要性以及安装路径的最佳实践,帮助用户避开常见陷阱,确保器件库安装一次成功。

weixin_33713707的博客 514

前端直连三模型智能路由:GPT-4o、Claude 3.5与国产大模型协同实践

大语言模型(LLM)并非单一技术标准,而是呈现显著的能力分形——GPT-4o代表多模态交互基线,Claude 3.5体现链式推理范式演进,国产大模型则承载中文语境适配与高性价比落地需求。其核心原理在于任务特征驱动的动态路由:通过输入长度、代码标识、法律术语等轻量信号,实时决策调用路径,规避串行延迟与平台锁定。该架构的技术价值在于解耦密钥管理、归一化错误响应、标准化输出结构,并实现前端沙箱内安全执行。典型应用场景包括技术文档撰写、合同条款解析、数学推导比对及跨模型结果横向评估,尤其适用于需‘一次输入、三方并发

weixin_30731305的博客 370

从零到一:手把手教你用Python+LangChain搭建企业级RAG知识库(附避坑指南)

本文为开发者提供了一份详尽的实战指南,手把手教你使用Python和LangChain框架从零构建企业级RAG知识库。内容涵盖环境搭建、文档处理、向量化检索、提示工程及生产部署等核心环节,并重点分享了文档分割、检索优化等关键避坑经验,旨在帮助读者打造稳定、高效且易于维护的智能知识中枢。

weixin_29058331的博客 398

通达信K线主图指标公式实战:如何用颜色标记快速识别涨停与炸板信号

本文详细介绍了如何利用通达信K线主图指标公式,通过颜色标记快速识别涨停与炸板等关键信号。通过实战拆解公式源码,手把手教您构建直观的“视觉交易系统”,将复杂的K线形态转化为醒目的颜色信号,帮助投资者高效聚焦机会与风险,提升技术分析效率。

weixin_29302047的博客 1758

Vibe Coding:一种以自然语言驱动的全栈开发新范式

Vibe Coding 是一种正在兴起的软件开发范式,其核心是将人类对功能的自然语言描述,直接转化为可运行、可调试、可演进的全栈代码。它并非传统AI编程助手的简单升级,而是依托语义沙盒、栈式生成与开发会话三大技术支柱,实现意图理解→上下文感知生成→持续演进的闭环。该范式显著降低个体开发者的技术门槛,同时提升企业级SaaS交付的一致性与可维护性,尤其在React+Tailwind+Node.js等具备高语义对齐度的技术栈中表现突出。它正推动开发重心从语法实现转向业务意图建模,重塑程序员的核心能力边界。

weixin_30607029的博客 444

(第78天)DB RU 补丁升级:19C 升级到 19.22

目前 Oracle 19C 是最新的稳定支持的版本,生产环境中使用的越来越多。当然,随着客户使用量的增多,自然无可避免的产生了很多 BUG,Oracle 每季度都会发布一个 RU 补丁来修复当前季度所产生的一些重要 BUG 补丁。作为 DBA,DB 补丁修复必然是需要掌握的一项技能。本文将介绍如何将数据库升级到最新的 RU 版本。

LuciferLiu_DBA 845

ROS快速入门杰哥教程1-77完整版

之前2月14号14点交了个残缺版,现在把C++代码补上,虽然学到一半科研室学长要求我们只用学Python部分就行,我想还是把C++补上吧,毕竟学了一多半还剩下小部分。过年那几天没学,3月18号和19号终于把这个77节课的笔记写完了,这是寒假留的1月份作业,里面有赶进度导致笔记欠佳,也有时间充裕时保姆式的笔记,写在了一块有点多,这是我首次超过10万字的笔记,未来我会继续不断提升自己。1.ROS是什么系统中加入IMU传感器,IMU作用是附着在机器人身上,实时发布机器人的旋转倾斜这些姿态信息的单元模块。

2501_93696036的博客 547

GPU硬件架构与微架构深度解析28-稀疏计算:稀疏矩阵计算的硬件支持

本文介绍了GPU加速稀疏计算的关键技术。主要内容包括:1)稀疏数据的存储格式(COO、CSR、CSC)及其特点;2)现代GPU的稀疏计算硬件优化,如NVIDIA的稀疏张量核心和内存访问优化;3)稀疏计算在推荐系统、NLP和科学计算等领域的应用案例;4)性能优化技巧,包括存储格式选择、硬件特性利用和混合精度计算等。文章指出,专用稀疏计算技术可显著提升AI和大规模科学计算的效率,相比传统方法可获得5-10倍的性能提升。

2301_79143213的博客 113

SSE(Server-Sent Events)完整使用示例

本篇使用Node.js 作为服务端,在浏览器客户端演示SSE的完整实例和演示。实现了一个基于 Server-Sent Events (SSE) 的实时数据推送功能。

oscar999的专栏 750

OpenClaw Windows 部署实操指南:5分钟跑通AI自动化智能体

AI智能体(Agent)是大模型落地办公自动化的关键范式,其核心在于触发-推理-执行的闭环能力。OpenClaw 作为面向终端用户的免代码智能体框架,聚焦本地化、低依赖与Windows友好性,通过封装17个即用型Skill、直连Ollama本地大模型、SQLite轻量存储等设计,显著降低Agent应用门槛。它不依赖云API、无需Python开发经验,特别适合行政、运营、教务等非技术岗位快速构建邮件监听、Excel生成、企业微信通知等真实场景自动化流程。本文详解Windows平台下零基础部署路径、四大硬性前置

weixin_30425949的博客 371

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

iOS随笔_网络(Socket/MQTT)

IP Internet Protocol 网络层协议,网络之间互联的协议。FTP File Transfer Protocol 文本传输协议TCP Transmission Control Protocol 传输控制器协议UDP User Datagram Protocol 用户数据报协议 HTTP HyperText Transfer Protocol 超文本传输协议 国际标准

Code_浅蓝 4609

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

NSTimer循环引用分析,解决

NSTimer常见用法 @interface TimerClass : NSObject - (void)start; - (void)stop; @end @implementation TimerClass { NSTimer *_timer; } - (id)init { return [super init]; } - (void)dealloc { NSLo...

Code_浅蓝 3799

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

内存管理(二) - MRC关键字解读

本篇主要学习以下几个知识点 alloc/reatin/release/dealloc 理解 autorelease 理解 autorelease GUN 实现 autorelease 苹果 实现 原文地址alloc/reatin/release/dealloc 实现我们来看看 GUNstep 源代码中 NSObject 类的的 alloc 类方法。id obj = [NSObject alloc];

Code_浅蓝 1856

iOS 多环境配置六张图就够了

在工作中我们需要配置不同的环境,说白了就是配置不同的编译环境,这里所谓的开发、测试、生产环境只不过是见名知意,或者服务器给定不同的访问地址。让它们各司其职,分工明确。第一张点击创建的工程,右键点击 Duplicate ,会生产一个 Text1的Copy 的工程 和一个list文件,我们可以修改成 你所定义的名字 。第二张第三张我们还可以配置多种ICON, 在 Assets.xcassets 中 添加

Code_浅蓝 1302

编写高质量iOS与OS X代码的52个有效方-Effective Objective-C 2.0阅读笔记

第1条:了解基本OC对象NSString *someString = @"The String";这种语法基本上是办照C语言的,它声明一个名为 someString的变量,类型为NSString* 。也就是说此变量指向 NSString的指针。所有Objective-C语言的对象都必须这样声明,因为对象所占内存总是分配在”“堆空间”(heap space)中, 而绝不会分配在”“栈”(stack)上

Code_浅蓝 1108

iOS 开发中常见Property关键字解读

本文用作对nonatomic和atomic,retain,weak,strong,assgin;还有深拷贝和浅拷贝,还是copy和strong修饰字符串的区别,一些iOS知识点的纪录,学习。还有非常多的不足,感谢您的斧正!

Code_浅蓝 1092

Book - Objective-C高级编程

1.1什么是自动引用计数关于ARC技术,最重要的还是下面这一点:++在LLVM编译器中设置ARC为有效状态,就无需再次键入retain或者是release代码。++1.2 内存管理/引用计数1.2.1 概要OC中的内存管理,也就是引用计数。可以用开关灯房间的案例来说明:假设办公室照明设备只有一个。上班的人进入办公室需要照明,所以把灯打开。而队对于下班离开办公室的人来说,已经不需要照明了,所以把等关掉

Code_浅蓝 976

WebViewJavascriptBridge

混合开发中, 重点在于Native与H5的混合使用,那么JavaScript 和 Objective-C 交互也就成为了重中之重。JS与OC的交互iOS方向大致分为三种:传统WebView的代理方法、JavaScriptCore、第三方框架。本文围绕目前优秀的第三方框架 WebViewJavascriptBridge 展开.1. 准备文件, 导入 WebViewJavascriptBridge$ p

Code_浅蓝 937

iOS 复习笔记 UISlider基础篇(一)

@porperty 1、value  --这个值是介于滑块的最大值和最小值之间的,如果没有设置边界值,默认为0-1; 2、minimumValue  --设置滑块最小边界值(默认为0) 3、maximumValue  --设置滑块最大边界值(默认为1) 4、minimumValueImage  --设置滑块最左端显示的图片 5、maximumValueImage  --设置

Code_浅蓝 885
上一篇: Html介绍
下一篇: iOS随笔_网络(Socket/MQTT)
Code_浅蓝
博客等级 码龄11年 28粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值