首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

ios app引起页面跳转

2013-09-21 
ios app唤起页面跳转有些时候我们需要再其他地方把app唤起,并打开跳转到指定的vc上面。这里我自己写了一个v

ios app唤起页面跳转

有些时候我们需要再其他地方把app唤起,并打开跳转到指定的vc上面。这里我自己写了一个vc的mgr,最主要的技术是method swizzle。原理就不详述,看代码吧。


////  ViewControllerMgr.m// ////  Created by Tommy on 13-8-14.//  Copyright (c) 2013年 Tommy. All rights reserved.//#import "ViewControllerMgr.h"#import <objc/runtime.h>#import <objc/objc.h>//static TomStack* s_vcStack = nil;static NSMutableDictionary* s_vcInitParametersDic = nil;#pragma mark -#pragma mark implement BaseViewControllerUIViewController * g_lastViewController = nil;#pragma mark -#pragma mark implement ViewControllerMgrstatic ViewControllerMgr* s_vcmgr = nil;@implementation ViewControllerMgr{    NSMutableDictionary* vcDic;        BOOL dispatchOpened;}- (id) init{    if(self =[super init])    {        vcDic = [NSMutableDictionary new];        _enablePresentOnSameVC = NO;        dispatchOpened = NO;                [self installHook];    }        return self;}+(id) sharedInstance{        static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        if (s_vcmgr == nil)        {            s_vcmgr = [[self alloc] init]; //autorelease];            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dispatchDelayedViewControllers) name:dispatch_delayed_notification_name object:nil];        }    });    return s_vcmgr;}+(id) allocWithZone:(NSZone *)zone{    @synchronized(self)    {        if (s_vcmgr == nil)        {            s_vcmgr = [super allocWithZone:zone];            return s_vcmgr;        }    }       return nil; }- (BOOL) handleUrl:(NSURL*)url {    NSAssert(_scheme,@"scheme is null");    NSAssert(_delegate,@"delegate is null");        @try {        if(url && _scheme && [_scheme isEqualToString:[url scheme]])        {            [[ViewControllerMgr sharedInstance] presentModalViewController:url];            return YES;        }    }    @catch (NSException *exception) {        NSLog(@"严重错误!!!!!");    }        return NO;}//register vc-(void) registerViewController:(NSString*)key  ClassName:(NSString*)vcName{    [self registerViewController:key  Class:NSClassFromString(vcName)];}-(void) registerViewController:(NSString*)key  Class:(Class) vcClass{    //if([vcClass isKindOfClass:[UIViewController class]])    [vcDic setObject:vcClass forKey:key];}- (void) registerViewController:(NSDictionary*)dic{    for(id obj in dic)    {        [self registerViewController:obj ClassName:[dic valueForKey:obj]];    }}//register#pragma mark -#pragma mark register vc init paramters- (void) registerInitParameters:(NSArray*) array ClassName:(NSString*)vcName{    if(!s_vcInitParametersDic)    {        s_vcInitParametersDic = [NSMutableDictionary new];    }        [s_vcInitParametersDic setValue:array forKey:vcName];}- (void) registerVCWithClassName:(NSString*)vcName{    [self registerInitParameters:@[[NSNull null]] ClassName:vcName];   }- (void) registerVCInitWithCoder:(NSCoder *)aDecoder ClassName:(NSString*)vcName{    [self registerInitParameters:@[aDecoder?aDecoder:[NSNull null],[NSNull null]] ClassName:vcName];}- (void) registerVCInitWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil ClassName:(NSString*)vcName{    [self registerInitParameters:@[nibNameOrNil?nibNameOrNil:[NSNull null],nibBundleOrNil?nibBundleOrNil:[NSNull null],[NSNull null]] ClassName:vcName];}//presetn vc- (NSDictionary*) parseURIQueryString:(NSString*)query{    NSMutableDictionary* param = [[NSMutableDictionary alloc] initWithCapacity:2];    NSArray* array = [query componentsSeparatedByString:@"&"];    for(NSString* ss in array)    {         NSArray* key = [ss componentsSeparatedByString:@"="];                switch ([key count]) {            case 1:                [param setValue:@"" forKey:[key objectAtIndex:0]];                break;            case 2:                [param setValue:[key objectAtIndex:1] forKey:[key objectAtIndex:0]];                break;            default:                break;        }    }    return param;}- (UIViewController*) createViewController:(NSString*) key parameters:(NSDictionary*) paramters{    UIViewController* vc = nil;    Class vcClass = [vcDic objectForKey:key];        if(vcClass)    {        if(_enablePresentOnSameVC && g_lastViewController && [g_lastViewController isKindOfClass:vcClass])        {            [self setParametersForVC:g_lastViewController paramters:paramters];          }        else        {            vc  =  [[vcClass alloc] initByVCMgr];            [self setParametersForVC:vc paramters:paramters];        }            }    else    {         NSAssert(0, @"call error %@ or %@ not inhert from BaseViewController",key,key);    }        return  vc;}- (void) setParametersForVC:(UIViewController*)vc paramters:(NSDictionary*) paramters{       for (id  key in paramters) {                @try {                        if(_delegate && [_delegate respondsToSelector:@selector(willSetParamter:key:value:)])            {               if([_delegate willSetParamter:vc key:key value:[paramters valueForKey:key]])               {                   [vc setValue:[paramters valueForKey:key] forKey:key];               }            }                    }        @catch (NSException *exception) {            NSLog(@"param invalid %@",paramters);//            NSAssert(0, @"param invalid %@",paramters);        }            }}//- (void) presentViewController:(NSString*)key//{//    [self presentModalViewController:key paramters:nil];//}- (void) presentModalViewController:(NSURL*)url{  if([_delegate willCreateVC:url ])  {      NSString* path = [[url pathComponents] lastObject];      NSString* key = path?path:[url host];      NSDictionary* parameters = [self parseURIQueryString:[url query]];      UIViewController* vc = nil;            if([_delegate respondsToSelector:@selector(creatViewController:paramters:)])      {          vc = [_delegate creatViewController:key paramters:parameters];      }            if(!vc)          vc = [self createViewController:key parameters:parameters];          if(vc && g_lastViewController)      {          UIViewController* onVC = g_lastViewController;                                              if(onVC && [_delegate willPresentVC:onVC currentVC:vc url:url] && vc != onVC)          {              if(onVC.navigationController)              {                  [onVC.navigationController pushViewController:vc animated:YES];              }              else              {                  //[vc setValue:@(YES) forKey:@"modalPresent"];                  UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];                                    [onVC presentModalViewController:nav animated:YES];              }          }      }  }}- (UIView*) topView{    return [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];}- (UIViewController*) topViewController{        return g_lastViewController;    }- (void) addToDelay:(NSURL*)aurl{    if(!_delayedUrlArray)    {        _delayedUrlArray = [NSMutableArray new];    }        for (NSURL* url in _delayedUrlArray) {        if([[url absoluteString] isEqualToString:[aurl absoluteString]])        {            return;        }    }    dispatchOpened = NO;    [_delayedUrlArray addObject:aurl];}- (void) dispatchDelayedViewControllers{        dispatchOpened = YES;    [self dispatchDelayedViewController];}- (void) dispatchDelayedViewController{    if ([_delayedUrlArray count])    {        NSURL * url = [_delayedUrlArray objectAtIndex:0];        if([_delegate willDispatchDelayedUrl:url])        {            if ([_delayedUrlArray count] ) {                [_delayedUrlArray removeObject:url];                [self handleUrl:url];            }                    }    }    }- (void) addViewControllerToDispatchQueue:(UIViewController*)vc{    }#pragma mark -#pragma mark hooked method imp//define #define Hooked_Orignal_Selector(_orgSelName) @selector(_vc_orignal_##_orgSelName)#define Hooked_Method(_name) _hooked_##_name#define Add_Method_To_Class(_class,_selName) do{    \    Method add_method = class_getInstanceMethod([self class], @selector(_selName)); \    IMP    add_imp = method_getImplementation(add_method);      \    class_addMethod(_class, @selector(_selName), add_imp, method_getTypeEncoding(add_method));    \}while(0)#define HOOK_OBJC_CLASS(_class,_orgSelName,_hookedSelName)  do{ \    Method org_method = class_getInstanceMethod(_class, @selector(_orgSelName));  \    Method rep_method = class_getInstanceMethod([self class], @selector(_hookedSelName));  \    IMP    org_imp = method_getImplementation(org_method);      \    class_addMethod(_class, Hooked_Orignal_Selector(_orgSelName), org_imp, method_getTypeEncoding(org_method)); \    IMP    rep_imp = method_getImplementation(rep_method); \    class_replaceMethod(_class, @selector(_orgSelName), rep_imp, method_getTypeEncoding(org_method));   \}while(0)#define Set_Instance_Var(_obj,_name,_value) objc_setAssociatedObject(_obj,"_append_"#_name,_value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)#define Get_Instance_Var(_obj,_name)        objc_getAssociatedObject(_obj,"_append_"#_name)#define REAL_SELF() UIViewController* realSelf = (UIViewController*)self- (void) installHook{        @try {        HOOK_OBJC_CLASS([UIViewController class],viewWillAppear:,Hooked_Method(viewDidAppearHooked:));        HOOK_OBJC_CLASS([UIViewController class],viewDidAppear:,Hooked_Method(viewDidAppear:));        HOOK_OBJC_CLASS([UIViewController class],presentModalViewController:animated:,Hooked_Method(presentModalViewController:animated:));                Add_Method_To_Class([UIViewController class],initByVCMgr);//        Add_Method_To_Class([UIViewController class],_modalClose:);//        Add_Method_To_Class([UIViewController class],_addCloseBtn:);//        Add_Method_To_Class([UIViewController class],goBack);//        Add_Method_To_Class([UIViewController class],goHome);                //class_addProperty need decalre in interface        //class_addIvar cannot support for exist class     }    @catch (NSException *exception) {        NSLog(@"install hook occur exception");    }    @finally {            }       }//hooked method//note//self not viewcontrollermgr, is viewcontroller instance//-(id) initByVCMgr{    REAL_SELF();    NSArray * parameters = [s_vcInitParametersDic valueForKey:[NSString stringWithUTF8String:class_getName([self class])]];    NSAssert(parameters, @"%@ initByVCMgr failed :init parameter error",self);        id  bself = nil;    switch ([parameters count]) {        case 1:            bself = [realSelf init];            break;        case 2:            bself = [realSelf initWithCoder:[parameters objectAtIndex:0]==[NSNull null]?nil:[parameters objectAtIndex:0]];            break;        case 3:            bself = [realSelf initWithNibName:[parameters objectAtIndex:0]==[NSNull null]?nil:[parameters objectAtIndex:0] bundle:[parameters objectAtIndex:1]==[NSNull null]?nil:[parameters objectAtIndex:1]];            break;        default:            NSAssert(parameters, @"%@ initByVCMgr failed:too many paramter:%@",self,parameters);            break;    }    if(bself)    {        Set_Instance_Var(self,presentByMgr, @(YES));    }        return bself;}- (void) Hooked_Method(viewWillAppear:(BOOL)animated){    [self performSelector:Hooked_Orignal_Selector(viewWillAppear:) withObject:@(animated)];    if(!g_lastViewController)    {        g_lastViewController = (UIViewController*)self;        [[ViewControllerMgr sharedInstance] performSelector:@selector(dispatchDelayedViewController)];    }}- (void) Hooked_Method(viewDidAppearHooked:(BOOL)animated){    [self performSelector:Hooked_Orignal_Selector(viewDidAppear:) withObject:@(animated)];    UIViewController* realSelf = (UIViewController*) self;    CGRect frame = realSelf.view.frame;        if(frame.origin.x == frame.origin.y && frame.origin.x == 0)        g_lastViewController = realSelf;        [[ViewControllerMgr sharedInstance] performSelector:@selector(dispatchDelayedViewController)];}- (void) Hooked_Method(presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated){    if([modalViewController isKindOfClass:[UINavigationController class]])    {        UINavigationController * nav = (UINavigationController*)modalViewController;                if([nav.viewControllers count])        {            Set_Instance_Var([nav topViewController],modalPresent, @(YES));        }    }else    {         Set_Instance_Var(modalViewController,modalPresent, @(YES));    }        [self performSelector:Hooked_Orignal_Selector(presentModalViewController:animated:) withObject:modalViewController withObject:@(animated)];}@end





热点排行