iOS开发之使用Runtime给Model类赋值

简介:

  本篇博客算是给网络缓存打个基础吧,本篇博客先给出简单也是最容易使用的把字典转成实体类的方法,然后在给出如何使用Runtime来给Model实体类赋值。本篇博客会介绍一部分,主要是字典的key与Model的属性名相同时,使用Runtime来进行赋值,下篇博客会给出字典key的值和Model的名字不同时的解决方案,并给出使用Runtime打印实体类属性值的方式。

  当然你可以使用KVC的setValuesForKeysWithDictionary:方法,下面的方法也是一种解决方案。如果使用setValuesForKeysWithDictionary:方法,则Model基类中必须得重写下面的方法,不然如果遇到字典的Key和modle的属性不对应的情况则会出现程序崩溃的情况。

-(void)setValue:(id)value forUndefinedKey:(NSString *)key{

}

  iOS开发中的Runtime可谓是功能强大,同时Runtime使用起来也是非常灵活的,今天博客的内容主要就是使用到一丁点的Runtime的东西。好废话不多说了进入今天的整体。

一、创建我们的测试工程

    在本测试工程中使用不到iOS开发的UI部分,所以我们就创建一个基于系统控制台的工程,主调用代码当然是放到main函数中了,Project创建过程如下图所示,Create new project -> OS X -> Application -> Command Line Tool ->一路next即可

  二、创建我们的测试数据

   1.首先使用for循环创建一个字典,当然字典的key和value在这是有规律的,下面的for循环是创建我们的测试数据,如果在有网络请求的状态下,该测试字典的来源就是你从网络请求的JOSN解析出来的字典,在这儿没有进行网络请求,因为网络请求不是本篇博客的重点,所以就使用for循环生成一个测试字典以供使用。创建测试字典的代码如下,改代码的位置放在main函数当中:

NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithCapacity:11];
 
 //创建测试适用的字典
 for(int i = 0; i <= 10; i ++){
 NSString *key = [NSString stringWithFormat:@"girl%d", i];
 
 NSString *value = [NSString stringWithFormat:@"我是第%d个女孩", i];
 
 [data setObject:value forKey:key];
 }

  上述代码生成字典,打印结果如下,可以看出字典是无序的,接下来就将data这个字典作为我们网络请求JSON解析后的字典来使用。

2015-07-20 22:33:15.742 BaseModelProject[65321:3224966] data = {
 girl0 = "我是第0个女孩";
 girl1 = "我是第1个女孩";
 girl10 = "我是第10个女孩";
 girl2 = "我是第2个女孩";
 girl3 = "我是第3个女孩";
 girl4 = "我是第4个女孩";
 girl5 = "我是第5个女孩";
 girl6 = "我是第6个女孩";
 girl7 = "我是第7个女孩";
 girl8 = "我是第8个女孩";
 girl9 = "我是第9个女孩";
}

  三、创建data字典对应的实体类

    接下来将会创建Data字典对应的实体类,首先将会实现实体类的属性名和字典的key值一致的情况,然后在下篇博客中将会实现如何把不同key值的字典转换成实体类的属性。

    1、首先我们先创建一个实体类,这个实体类要继承与实体基类,因为一些公用的方法是在实体基类中进行编写的,如便利构造器,便利初始化方法,把字典转成Model属性等方法回被抽象到这个基类当中。创建实体类如下图所示,创建类的时候选中创建的基类即可:

    2. 这个实体类的命名为:BeautifulGirlModel,下面是BeautifulGirlModel中的属性,属性的名字和字典key的值相同,如下所示,BaseModelObject是之前创建的基类,BaseModelObject继承与NSObject即可。

//
// BeautifulGirlModel.h
// BaseModelProject
//
// Created by Mr.LuDashi on 15/7/20.
// Copyright (c) 2015年 ludashi. All rights reserved.
//

#import "BaseModelObject.h"

@interface BeautifulGirlModel : BaseModelObject

@property (nonatomic, copy) NSString *girl0;
@property (nonatomic, copy) NSString *girl1;
@property (nonatomic, copy) NSString *girl2;
@property (nonatomic, copy) NSString *girl3;
@property (nonatomic, copy) NSString *girl4;
@property (nonatomic, copy) NSString *girl5;
@property (nonatomic, copy) NSString *girl6;
@property (nonatomic, copy) NSString *girl7;
@property (nonatomic, copy) NSString *girl8;
@property (nonatomic, copy) NSString *girl9;
@property (nonatomic, copy) NSString *girl10;

@end

  四、实现实体基类中的方法。

    实体基类中的方法是从各个Model中抽象出来的并且可以重复利用的部分,在实体基类的方法中大致包括:生成getter方法,生成setter方法,获取Model类的属性,把字典的值赋给对应的Model, 动态的调用getter方法对实体类的属性值进行遍历。本篇博客中回给出一部分,剩下的一部分会在以后的博客中陆续给出。

  1.根据Key值生成set方法

    首先要编写的方法是传入一个字符串,然后返回该字符串所对应属性的setter方法。这个方法其实很简单的,就是把对应的字符串的首字母大写并且拼接上set关键字,再生产SEL并返回,该方法的具体实现如下:

#pragma mark -- 通过字符串来创建该字符串的Setter方法,并返回
- (SEL) creatSetterWithPropertyName: (NSString *) propertyName{
 
 //1.首字母大写
 propertyName = propertyName.capitalizedString;
 
 //2.拼接上set关键字
 propertyName = [NSString stringWithFormat:@"set%@:", propertyName];
 
 //3.返回set方法
 return NSSelectorFromString(propertyName);
}

  2.把字典传入到方法中,并把字典的值赋给相应实体类的属性,该方法需要调用上述方法来生成setter方法,通过setter方法把字典的Value赋值给实体类对应的属性,代码如下,下面代码中的注释还是比较详细的,具体细节就参考下面注释的内容了。通过调用这个方法就可以把字典的值赋给对应的实体类的属性,调用这个方法的前提是要求字典的key与实体类的属性名必须相同。有的小伙伴会问如果不一样该怎么做呢?这个问题到下篇博客中在进行介绍。

/************************************************************************
 *把字典赋值给当前实体类的属性
 *参数:字典
 *适用情况:当网络请求的数据的key与实体类的属性相同时可以通过此方法吧字典的Value
 * 赋值给实体类的属性
 ************************************************************************/

-(void) assginToPropertyWithDictionary: (NSDictionary *) data{
 
 if (data == nil) {
 return;
 }
 
 ///1.获取字典的key
 NSArray *dicKey = [data allKeys];
 
 ///2.循环遍历字典key, 并且动态生成实体类的setter方法,把字典的Value通过setter方法
 ///赋值给实体类的属性
 for (int i = 0; i < dicKey.count; i ++) {
 
 ///2.1 通过getSetterSelWithAttibuteName 方法来获取实体类的set方法
 SEL setSel = [self creatSetterWithPropertyName:dicKey[i]];
 
 if ([self respondsToSelector:setSel]) {
 ///2.2 获取字典中key对应的value
 NSString *value = [NSString stringWithFormat:@"%@", data[dicKey[i]]];
 
 ///2.3 把值通过setter方法赋值给实体类的属性
 [self performSelectorOnMainThread:setSel
 withObject:value
 waitUntilDone:[NSThread isMainThread]];
 }
 
 }
 
}

  3.接下来就是开始编写实体类的入口了,也就是便利初始化方法和便利构造器。并在头文件中留出接口,下面先给出便利初始化方法然后在给出便利构造器。

    (1)下面的代码是实体类的便利初始化方法,当然是实例方法,该方法需要传入一个字典,这个字典中的key就是该实体类的属性名,值就是要给该实体类的属性赋的值。并且返回该实体类的实例,简单的说就是调用-(void) assginToPropertyWithDictionary: (NSDictionary *) data方法,具体代码如下:

- (instancetype)initWithDictionary: (NSDictionary *) data{
 {
 self = [super init];
 if (self) {
 [self assginToPropertyWithDictionary:data];
 }
 return self;
 }
}

    (2)下面将要给出便利构造器,当然便利构造器是类方法,并且返回该类的一个实例。用大白话说,便利构造器就是分配内存后调用便利初始化方法然后返回该对象的实例,下方是实体类对应的便利构造器:

1 + (instancetype)modelWithDictionary: (NSDictionary *) data{
2 
3 return [[self alloc] initWithDictionary:data];
4 
5 }

  五、测试上面的代码

    上面运行这么多了得运行一下代码看一下结果吧。因为我们这是基于系统的控制台程序,所以我们需要在main函数中进行调用我们编写的方法,需要把我们上面生成的测试字典传入到实体类的构造器中,并且获取实体类的一个实例。该获取的实体类的实例中的属性就已经被赋值上了传入的字典的值。具体调用方法如下所示。

1 BeautifulGirlModel *beautifulGirl = [BeautifulGirlModel modelWithDictionary:data];
2 
3 NSLog(@"%@", beautifulGirl.girl0);

  运行结果如下:

  使用setValuesForKeysWithDictionary方法赋值,测试代码如下:

 BeautifulGirlModel *beautifulGirl = [[BeautifulGirlModel alloc] init];
 [beautifulGirl setValuesForKeysWithDictionary:data];

  最后给出最笨的赋值方法,也是最容易学会的赋值方法,不过这种方式维护起来回不太方便,而且大部分做的都是体力活的,实例如下:

BeautifulGirlModel *beautifulGirl1 = [[BeautifulGirlModel alloc] init];
 beautifulGirl1.girl0 = data[@"girl0"];
 beautifulGirl1.girl1 = data[@"girl1"];
 beautifulGirl1.girl2 = data[@"girl2"];
 beautifulGirl1.girl3 = data[@"girl3"];
 beautifulGirl1.girl4 = data[@"girl4"];
 beautifulGirl1.girl5 = data[@"girl5"];
 beautifulGirl1.girl6 = data[@"girl6"];
 beautifulGirl1.girl7 = data[@"girl7"];

相关文章
|
4天前
|
Swift iOS开发 Kotlin
苹果iOS新手开发之Swift中实现类似Kotlin的作用域函数
Swift可通过扩展实现类似Kotlin作用域函数效果。如自定义`let`, `run`, `with`, `apply`, `also`,增强代码可读性和简洁性。虽无直接内置支持,但利用Swift特性可达成相似功能。
23 7
|
1天前
|
移动开发 前端开发 iOS开发
探索iOS开发的未来:SwiftUI与Combine的融合
随着苹果公司不断推进其操作系统的更新,iOS开发领域也迎来了诸多变革。在这篇文章中,我们将深入探讨SwiftUI和Combine这两个强大的框架,它们如何共同塑造着iOS应用开发的未来趋势。通过具体实例和数据支持,本文旨在揭示这些技术如何简化开发者的工作流,提升用户界面构建的效率,以及加强应用的响应性和性能表现。我们还将提出一个开放性问题,邀请读者思考并探索这些技术在未来可能带来的进一步影响。 【7月更文挑战第26天】
9 2
|
3天前
|
API 数据处理 开发工具
探索iOS开发的未来:SwiftUI和Combine的融合
【7月更文挑战第23天】随着Apple不断推动其软件开发工具的创新,SwiftUI和Combine框架的出现标志着iOS开发进入了一个新的时代。本文将深入探讨这两个框架如何简化界面设计和事件处理,以及它们如何共同为开发者提供一个更加高效、声明式的编程模型。我们将通过实际示例来展示如何利用SwiftUI构建用户界面,并使用Combine处理异步事件和状态管理。文章还将预测这些技术如何塑造iOS应用开发的未来趋势。
|
2天前
|
调度 Swift Android开发
苹果iOS新手开发之Swift中的并发任务和消息机制
Swift的消息机制类似Android的Handler,实现任务调度有三种方式: 1. **Grand Central Dispatch (GCD)**:使用`DispatchQueue`在主线程或后台线程执行任务。 2. **OperationQueue**:提供高级接口管理`Operation`对象。 3. **RunLoop**:处理事件如输入源、计时器,类似Android的`Looper`和`Handler`。 **示例**: - GCD:在不同线程执行代码块。 - OperationQueue:创建操作并执行。 - RunLoop:用Timer添加到RunLoop中。
12 2
|
3天前
|
前端开发 Android开发 iOS开发
探索安卓与iOS开发的差异性与互补性
在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统各据一方,引领着市场潮流。它们在技术架构、开发环境及用户群体等方面展现出独特的差异性,同时也存在着潜在的互补性。本文将深入剖析这两种平台的开发细节,从不同角度揭示其各自优势及相互之间的协同潜力,为开发者提供全面而深刻的视角。
10 2
|
5天前
|
Unix 调度 Swift
苹果iOS新手开发之Swift 中获取时间戳有哪些方式?
在Swift中获取时间戳有四种常见方式:1) 使用`Date`对象获取秒级或毫秒级时间戳;2) 通过`CFAbsoluteTimeGetCurrent`获取Core Foundation的秒数,需转换为Unix时间戳;3) 使用`DispatchTime.now()`获取纳秒级精度的调度时间点;4) `ProcessInfo`提供设备启动后的秒数,不表示绝对时间。不同方法适用于不同的精度和场景需求。
17 3
|
7天前
|
Swift iOS开发 开发者
探索iOS开发中的SwiftUI框架
【7月更文挑战第19天】在移动应用开发的浪潮中,苹果公司的SwiftUI框架如同一股清新的海风,为iOS开发者带来了前所未有的编程体验。本文将深入探讨SwiftUI的核心特性,揭示其如何简化界面设计流程,提升开发效率,并展望SwiftUI在未来iOS开发领域的发展潜力。通过实例分析,我们将一同见证SwiftUI如何塑造更加直观、高效的编程模式。
|
4天前
|
前端开发 Swift iOS开发
探索iOS开发的未来:SwiftUI和Combine的融合
在iOS开发领域,SwiftUI和Combine框架的出现标志着一个新时代的到来。本文深入探讨这两个框架如何共同推动iOS应用开发的现代化,通过具体案例分析它们的优势、挑战以及未来趋势。
|
4天前
|
数据处理 Swift iOS开发
探索iOS开发的未来之路:SwiftUI和Combine框架的融合
在本文中,我们将深入探讨iOS开发的新趋势——SwiftUI和Combine框架的结合使用。我们将从这两个框架的基本概念入手,逐步解析它们如何协同工作,以实现更加高效、响应式的用户界面构建。通过实例演示,我们将揭示这种组合如何简化代码结构,提高开发效率,并增强应用性能。最后,我们将展望这种技术栈在未来iOS开发中的潜在影响和应用前景。
|
10天前
|
Java Android开发 iOS开发
探索安卓与iOS开发的差异性与互操作性
【7月更文挑战第17天】在移动应用开发的广阔天地中,安卓和iOS这两大操作系统如同双子星座般璀璨夺目。它们各自拥有独特的开发环境、编程语言和用户群体,为开发者提供了不同的挑战和机遇。本文将从多个维度深入剖析安卓与iOS开发的差异性,并探讨它们之间的互操作性如何实现,以期为开发者们提供一份实用的指南。
24 7