A collection of iOS demos.
- 引入头文件 DMMacros.h, DM 是 Demo 的缩写.
- 注入一个 item, identifier 是必须的,class 也是必须的, 在这里是 DMSampleViewController.
- 愉快地 Coding.
#import "DMSampleViewController.h"
// 1. import Macros
#import "DMMacros.h"
// 2. register an item corresponding to your view controller
dm_registerDemo(DMSampleViewController, {
item.identifier = @"Sample.UIButton"; // identifier required
})
// 3. enjoy coding with this view controller :)
@interface DMSampleViewController ()
@end
@implementation DMSampleViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
}
@end
日常写了一些 demo,但是重复劳动很多,并且无法很好收集整理起来,供后续查找,更无法分享给别人了。所以希望有个 demo 列表, 像下边这个样子。
====================
Main VC
=============
demo list
---
demo 1 --> subVC
---
demo 2 --> subVC
---
demo 3 --> subVC
---
====================
然而有了这个想法之后,越来越多的想法开始出现。
-
要方便书写,避免重复劳动,避免如下情况:
#import "SceneDelegate.h" #import "DMBaseViewController.h" #import "BDMSyntaxController.h" #import "VerticalSlidingViewController.h" #import "DMHitTestViewController.h" #import "DMCollectionViewDragViewController.h" #import "DMLayoutViewController.h" #import "DMPassThroughViewController.h" #import "DMSampleViewController.h"
-
要有说明文字,要有 icon、author、hyperlink
-
要易于检索,搞个简单的搜索的VC, 方便跳转
-
要解耦,或者容易修改,上述的信息,在注入后,要能容易拿取到。
因为不想分散多处写注入代码, 最好是能像注解一样,只做一个操作,就注入。
@registerItem("Sample.Button.Basic")
@interface DMSampleViewController
@end
但是在 Objc 中,确实没有找到比较方便的实现,但是又非常想要这种效果。考虑过几种实现:
-
VC 继承的方式进行注入 --> Objc 不能多继承, 限制了 Demo 的能力
-
接口注入到全局 mountArray --> 添加操作需要运行时完成,否则需要静态注入。
/// in mount file static NSArray<id<DMInjectProtocol>> *mountArray = @[ [DMSampleViewController class], ] /// in DMSampleViewController.m @interface DMSampleViewController()<DMInjectProtocol> @end
-
因此不得不找些运行时注入的方式,或者编译预处理的操作,考虑过
- LazyRegister, 注入函数指针到 data 段,会在 section 引入的时候注入,运行时机可选。
- load 方法, 运行时机在 main 函数之前,但是需要写 C 方法。
- Category 运行时注入,生成特定函数,但是 Demo 多了之后,会生成很多小Category. 【Selected】
因为是 demo 项目,没有必要过度设计,所以选择了简单的方式实现,遇到问题再优化。
dm_registerDemo 宏 最终生成”一条分类“,一条 : ) 合乎文法 : )
@interface DMRegisterCenter( DMSampleViewController ) - (void)user_registerItemsFor_DMSampleViewController;@end; @implementation DMRegisterCenter( DMSampleViewController ) - (void)user_registerItemsFor_DMSampleViewController{ [self registerClass:@"DMSampleViewController" withBlock:^(DMRegisterItem *item) { { item.identifier = @"Sample.UIButton";} }]; }@end
在 RegisterCenter 中会去遍历自己的实例方法,找到用户注入的方法(@user_ 开头)
- (void)loadAllItemsFromCategories
{
unsigned int count;
Method *methods = class_copyMethodList([self class], &count);
for (int i = 0; i < count; i ) {
SEL methodSelector = method_getName(methods[i]);
NSString *methodName = [NSString stringWithUTF8String:sel_getName(methodSelector)];
if ([methodName hasPrefix:@"user_"]) {
[self performSelector:methodSelector];
}
}
free(methods);
}
虽然用 user_ 打头这个方式,看起来很trick, 但是很方便。
目前的这种方式,对于VC没有任何的约束,您可以去做任何的事情,我们来负责检索,提供方便的工具。
约定:
- dm_registerDemo 的第一个参数是需要注入的 ViewController 类名
- dm_registerDemo 中使用 item 对象进行配置
- identifier 的命名,使用
.
进行分隔,例如 "Sample.Button.Basic", 将用于检索,一般不超过三段。 - 目录放置根据 identifier 的分段分目录放置
- 完善初始界面
- 添加检索功能
- 添加基础UI组件:用户信息,代码块,说明文字。
- 2022-10-5: complete injection