自己写的一个ios框架,把页面跳转和对象的创建全部提出,降低耦合,开发者只关注功能的开发。...

最近项目活比较少,没事写了一个框架,也是对以前开发的总结。那我写这个是干嘛用呢? 我把app中页面的跳转用xml描述,程序会自动解析,各页面对象的创建也由框架管理创建,这样由老大搞好流程,下面小弟就只关心各自负责的页面功能开发就行。低耦合,高内聚。     先看下图。其中frame是核心部分。另外借用了第三方LCNavigationController和GDataXML。前者是页面跳转,后者是xml解析。如何使用自行百度。

上图中的datainfo.xml文件就是页面跳转的逻辑描述。

是这个样子:

<?xml version="1.0" encoding = "UTF-8"?>
<info>
   <class>
      <classname>ViewController</classname>
      <nextclass>
          <nextclassname>
              <id>Test2</id>
              <name>Test2Controller</name>
          </nextclassname>
      </nextclass>
   </class>
   <class>
      <classname>Test2Controller</classname>
      <nextclass>
          <nextclassname>
              <id>Test3</id>
              <name>Test3Controller</name>
          </nextclassname>
          <nextclassname>
              <id>Test4</id>
              <name>Test4Controller</name>
          </nextclassname>
      </nextclass>
      <prevclass>
          <prevclassname>
              <id>View</id>
              <name>ViewController</name>
          </prevclassname>
      </prevclass>
   </class>
   <class>
      <classname>Test3Controller</classname>
      <prevclass>
          <prevclassname>
              <id>Test2</id>
              <name>Test2Controller</name>
          </prevclassname>
      </prevclass>
   </class>
   <class>
      <classname>Test4Controller</classname>
      <prevclass>
          <prevclassname>
              <id>Test2</id>
              <name>Test2Controller</name>
          </prevclassname>
      </prevclass>
   </class>
</info>

标签<class></class>为一组。<classname>是当前的页面,<nextclassname>是跳转下一个页面,<prevclassname>是返回上一个页面。结构还是很简单的。

Manager是单例类(单例怎么写,不用我介绍了)。主要是解析xml文件和初始化。看截图:

-(void) loadorganizationformdatainfo{
    NSString *filePath=[[NSBundle mainBundle] pathForResource:@"datainfo" ofType:@"xml"];
    NSData *xmlData = [[NSData alloc] initWithContentsOfFile:filePath];
    classtreedic = [[NSMutableDictionary alloc] init];
    //使用NSData对象初始化
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData  options:0 error:nil];
    NSString *Name;
    //获取根节点(Users)
    GDataXMLElement *rootElement = [doc rootElement];
    NSArray *anyTypes=[rootElement elementsForName:@"class"];
    for (GDataXMLElement *anyType in anyTypes ) {
        //主体部分,class名字。
        GDataXMLElement *NameID=[[anyType  elementsForName:@"classname"] objectAtIndex:0];
        Name = [NameID stringValue];
        nodeclass = [[Classmodel alloc] init];
        nodeclass.prevclassnamedict = [[NSMutableDictionary alloc] init];
        nodeclass.nextclassnamedict = [[NSMutableDictionary alloc] init];
        [nodeclass setClassname:Name];
        NSLog(@"name is %@",Name);
        
        //跳转下一个class设定
        GDataXMLElement *enextclass = [[anyType elementsForName:@"nextclass"] objectAtIndex:0] ;
        NSArray *types = [enextclass elementsForName:@"nextclassname"];
        for (GDataXMLElement *eType in types) {
            //GDataXMLElement *nextclassname=[[eType  elementsForName:@"nextclassname"] objectAtIndex:0];
            NSString  *str_id = [[[eType elementsForName:@"id"] objectAtIndex:0] stringValue];
            NSString *str_nextclassname = [[[eType elementsForName:@"name"] objectAtIndex:0] stringValue];
            [nodeclass.nextclassnamedict setValue:str_nextclassname forKey:str_id];
            NSLog(@"nextclassID is %@",str_id);
            NSLog(@"nextclassname is %@",str_nextclassname);
        }
        //返回上一个class设定
        GDataXMLElement *eprevclass = [[anyType elementsForName:@"prevclass"] objectAtIndex:0] ;
        NSArray *ptypes = [eprevclass elementsForName:@"prevclassname"];
        for (GDataXMLElement *pType in ptypes) {
            //GDataXMLElement *nextclassname=[[eType  elementsForName:@"nextclassname"] objectAtIndex:0];
            NSString  *str_id = [[[pType elementsForName:@"id"] objectAtIndex:0] stringValue];
            NSString *str_prevclassname = [[[pType elementsForName:@"name"] objectAtIndex:0] stringValue];
            [nodeclass.prevclassnamedict setValue:str_prevclassname forKey:str_id];
            NSLog(@"prevclassID is %@",str_id);
            NSLog(@"prevclassname is %@",str_prevclassname);
        }
        [classtreedic setValue:nodeclass forKey:Name];
    }
    NSLog(@"%@",classtreedic);
    
}

-(void) initforclassname:(UIViewController *)classforVC{
    NSString *classname = NSStringFromClass([classforVC class]);
    self.nodeclass = [classtreedic objectForKey:classname];
    NSLog(@"self.nodeclass = %@",self.nodeclass);
    self.nowclass = [[currectclass alloc] init];
    self.nowclass.currclass = classforVC;
    self.nowclass.nodeclass = self.nodeclass;
    
}

只有两个方法。一看就明白。再看这里。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [[Manager shareInstance] loadorganizationformdatainfo];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    ViewController *VC = [[ViewController alloc] init];
    self.rootviewcontroller = [[LCNavigationController alloc] initWithRootViewController:VC ];
    self.window.rootViewController = self.rootviewcontroller;
    [[Manager shareInstance] initforclassname:VC];
    return YES;
}

上图中可以看到那俩方法。

//主体调度,单例模式
#import <UIKit/UIKit.h>
#import "Classmodel.h"

@interface currectclass : NSObject
@property(retain,nonatomic) UIViewController *currclass;
@property(retain,nonatomic) Classmodel *nodeclass;
@end

@interface Manager : NSObject
@property(retain,nonatomic) currectclass *nowclass;

@property(retain,nonatomic) Classmodel *nodeclass;
@property(retain,nonatomic) NSMutableDictionary<NSString *, Classmodel *> *classtreedic;


+(instancetype) shareInstance;
-(void) loadorganizationformdatainfo;
-(void) initforclassname:(UIViewController *)classforVC;
@end

classtreedic是解析xml后存放的字典数据。这个本来是考虑写成链表的,但最后考虑没必要那么麻烦。nodeclass就代表xml中每一组<class></class>。nowclass是当前页面活动的对象信息。可看currectclass的定义。Classmodel的定义看这里:

/数据模型,对于datainfo里的一组class具体表现
#import <UIKit/UIKit.h>



@interface ToClassmodel : NSObject

@property (strong, nonatomic) NSString *toclassname;

@end

@interface Classmodel : NSObject

@property (strong, nonatomic) NSString *classname;
@property (nonatomic, retain) NSDictionary<NSString *,ToClassmodel *> *prevclassnamedict;
@property (nonatomic, retain) NSDictionary<NSString *,ToClassmodel *> *nextclassnamedict;

@end

下面介绍Manager+route。这个本来是可写在manager里的。但考虑用分类的话,看起来更清楚一些。下图是方法的定义。有八个方法,一个页面可能会跳向不同的页面,有时还会携带参数。所以就有八个了。

#import "Manager.h"

@interface Manager (route)

-(void)completetonextview;
-(void)completetonextviewfordata:(NSDictionary *)datadic;
-(void)completetonextviewbyid:(NSString *)classid;
-(void)completetonextviewbyid:(NSString *)classid fordata:(NSDictionary *)datadic;

-(void)completetoprevview;
-(void)completetoprevviewfordata:(NSDictionary *)datadic;
-(void)completetoprevviewbyid:(NSString *)classid;
-(void)completetoprevviewbyid:(NSString *)classid fordata:(NSDictionary *)datadic;

@end

 

#import "Manager+route.h"
#import "Classmodel.h"
#import "AppDelegate.h"
#import "LCNavigationController.h"
#import <objc/runtime.h>

@implementation Manager (route)

-(void)completetonextview{
    [self completetonextviewbyid:nil fordata:nil];
}

-(void)completetonextviewfordata:(NSDictionary *)datadic{
    [self completetonextviewbyid:nil fordata:datadic];
}

-(void)completetonextviewbyid:(NSString *)classid{
    [self completetonextviewbyid:classid fordata:nil];
}

-(void)completetonextviewbyid:(NSString *)classid fordata:(NSDictionary *)datadic{
    NSString *Toclassname = [self gettoclassname:classid fordic:self.nowclass.nodeclass.nextclassnamedict];
    if (Toclassname == nil) {
        return;
    }
    Class ToClass = NSClassFromString(Toclassname);
    [ToClass self];
    id obj = [[ToClass alloc] init];
    //赋值跳转
    if (datadic != nil) {
       NSArray *kaylist = [datadic allKeys];
       for (NSString *kay in kaylist) {
           if ([self getVariableWithClass:ToClass varName:kay]) {
              [obj setValue:[datadic objectForKey:kay] forKey:kay];
           }
       }
    }
    AppDelegate *app =(AppDelegate *) [UIApplication sharedApplication].delegate;
    
    LCNavigationController *rootViewController = (LCNavigationController *)(app.window.rootViewController);
    [rootViewController pushViewController:obj];
    //记录当前对象
    self.nowclass.currclass = obj;
    self.nowclass.nodeclass = [self.classtreedic objectForKey:Toclassname];
}

-(void)completetoprevview{
    [self completetoprevviewbyid:nil fordata:nil];
}

-(void)completetoprevviewfordata:(NSDictionary *)datadic{
    [self completetoprevviewbyid:nil fordata:datadic];
}

-(void)completetoprevviewbyid:(NSString *)classid{
    [self completetoprevviewbyid:classid fordata:nil];
}

-(void)completetoprevviewbyid:(NSString *)classid fordata:(NSDictionary *)datadic{
    NSString *Toclassname = [self gettoclassname:classid fordic:self.nowclass.nodeclass.prevclassnamedict];
    if (Toclassname == nil) {
        return;
    }
    Class ToClass = NSClassFromString(Toclassname);
    [ToClass self];
    id obj = [[ToClass alloc] init];
    //赋值跳转
    if (datadic != nil) {
        NSArray *kaylist = [datadic allKeys];
        for (NSString *kay in kaylist) {
            if ([self getVariableWithClass:ToClass varName:kay]) {
                [obj setValue:[datadic objectForKey:kay] forKey:kay];
            }
        }
    }
    AppDelegate *app =(AppDelegate *) [UIApplication sharedApplication].delegate;
    
    LCNavigationController *rootViewController = (LCNavigationController *)(app.window.rootViewController);
    [rootViewController popToViewController:obj];
    //记录当前对象
    self.nowclass.currclass = obj;
    self.nowclass.nodeclass = [self.classtreedic objectForKey:Toclassname];
}

-(NSString *) gettoclassname:(NSString *)classid fordic:(NSDictionary *)dic{
    if (dic.count == 0) {
        return nil;
    }
    if (dic.count == 1) {
        return (NSString *)(dic.allValues[0]);
    }
    return (NSString *)[dic objectForKey:classid];
}

//判断是否包含一个属性
- (BOOL) getVariableWithClass:(Class) myClass varName:(NSString *)name{
    unsigned int outCount, i;
    Ivar *ivars = class_copyIvarList(myClass, &outCount);
    for (i = 0; i < outCount; i++) {
        Ivar property = ivars[i];
        NSString *keyName = [NSString stringWithCString:ivar_getName(property) encoding:NSUTF8StringEncoding];
        keyName = [keyName stringByReplacingOccurrencesOfString:@"_" withString:@""];
        if ([keyName isEqualToString:name]) {
            return YES;
        }
    } return NO;
}

@end

上图可看到具体的处理。就是利用反射原理创建所要跳转的对象。然后把参数赋值过去,最后用到LCNavigationController进行跳转。再把当前活动的对象信息(nowclass)更新。

好了,就这些,代码不多,基本能用,但不够完善。后续再完善吧。有大牛看到欢迎指点,以使我进步。

转载于:https://my.oschina.net/u/989459/blog/2045638

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值