本身寫的一個ios框架,把頁面跳轉和對象的建立所有提出,下降耦合,開發者只關注功能的開發。

最近項目活比較少,沒事寫了一個框架,也是對之前開發的總結。那我寫這個是幹嗎用呢? 我把app中頁面的跳轉用xml描述,程序會自動解析,各頁面對象的建立也由框架管理建立,這樣由老大搞好流程,下面小弟就只關心各自負責的頁面功能開發就行。低耦合,高內聚。     先看下圖。其中frame是核心部分。另外借用了第三方LCNavigationController和GDataXML。前者是頁面跳轉,後者是xml解析。如何使用自行百度。node

上圖中的datainfo.xml文件就是頁面跳轉的邏輯描述。app

是這個樣子:框架

<?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>是返回上一個頁面。結構仍是很簡單的。ide

Manager是單例類(單例怎麼寫,不用我介紹了)。主要是解析xml文件和初始化。看截圖:atom

-(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;
    
}

只有兩個方法。一看就明白。再看這裏。code

- (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;
}

上圖中能夠看到那倆方法。orm

//主體調度,單例模式
#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的定義看這裏:xml

/數據模型,對於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)更新。blog

好了,就這些,代碼很少,基本能用,但不夠完善。後續再完善吧。有大牛看到歡迎指點,以使我進步。

相關文章
相關標籤/搜索