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

//
// ViewControllerMgr.h
//
//
// Created by Tommy on 13-8-14.
// Copyright (c) 2013年 Tommy. All rights reserved.
// #import <Foundation/Foundation.h> @protocol ViewControllerMgrDelegate <NSObject> - (BOOL) willCreateVC:(NSURL*)url;
- (BOOL) willPresentVC:(UIViewController*)onVc currentVC:(UIViewController*) presentVC url:(NSURL*)url; //if return no, will not dispatch delay url
- (BOOL) willDispatchDelayedUrl:(NSURL*)url;
//- (BOOL) needchangeToNextVC:(UIViewController*)onVc; @optional
//if return no, will not set the param by vcmgr
//please set param by yourself in delegate, and return no
- (BOOL) willSetParamter:(UIViewController*)onVc key:(NSString*)key value:(NSString*)value; @optional - (UIViewController*) creatViewController:(NSString*)vcKey paramters:(NSDictionary*)parameters; @end #define dispatch_delayed_notification_name @"_dispatchDelayedViewControllers" @interface ViewControllerMgr : NSObject @property(weak) id<ViewControllerMgrDelegate> delegate; +(id) sharedInstance; //如果当前的vc刚好和需要显示的vc是同一个类,如果不需要再这个之上弹出,而只是修改当前vc的内容,请设置为YES,否则为NO
//默认为NO
@property (assign) BOOL enablePresentOnSameVC;
@property (strong) NSString * scheme;
//保持需要被推迟的vc 的url
@property (strong) NSMutableArray * delayedUrlArray; - (BOOL) handleUrl:(NSURL*)url; - (void) registerViewController:(NSString*)key ClassName:(NSString*)vcName;
- (void) registerViewController:(NSString*)key Class:(Class) vcClass;
- (void) registerViewController:(NSDictionary*)dic; //register vc init paramters
- (void) registerInitParameters:(NSArray*) array ClassName:(NSString*)vcName;
- (void) registerVCWithClassName:(NSString*)vcName;
- (void) registerVCInitWithCoder:(NSCoder *)aDecoder ClassName:(NSString*)vcName;
- (void) registerVCInitWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil ClassName:(NSString*)vcName; //delay
- (void) addToDelay:(NSURL*)url;
//call by
- (void) dispatchDelayedViewControllers;
- (void) addViewControllerToDispatchQueue:(UIViewController*)vc; //暂时不支持
//- (void) presentViewController:(NSString*)key;
//- (void) presentModalViewController:(NSString*)key paramters:(NSString*)paramters; - (void) presentModalViewController:(NSURL*)url; - (UIView*) topView;
- (UIViewController*) topViewController; @end
//
// 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 BaseViewController
UIViewController * g_lastViewController = nil; #pragma mark -
#pragma mark implement ViewControllerMgr
static 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

ios app唤起页面跳转的更多相关文章

  1. iOS APP之间到跳转,以及热门应用,手机自带到应用跳转

    应用之间的跳转 在第一个APP中,做如下操作:1.在info.plist文件中的"信息属性列表"下添加一项:"URL类型"; 2.点开"URL类型&q ...

  2. MUI框架开发HTML5手机APP(二)--页面跳转传值&底部选项卡切换

      概 述 JRedu 在上一篇博客中,我们学习了如何使用Hbuilder创建一个APP,同时如何使用MUI搭建属于自己的第一款APP,没有学习的同学可以戳链接学习: http://www.cnblo ...

  3. iOS——使用StroryBoard页面跳转及传值

    之前在网上搜iOS的页面跳转大多都是按回以前的那种xib的形式,但鄙人是使用storyboard的.这篇就只介绍利用storyboard进行页面跳转与传值. 新建页面 iOS的程序也是使用了MVC的思 ...

  4. iOS使用StroryBoard页面跳转及传值

    之前在网上iOS的页面跳转大多都是按回以前的那种xib的形式,但鄙人是使用storyboard的.这篇就只介绍利用storyboard进行页面跳转与传值. 新建页面 iOS的程序也是使用了MVC的思想 ...

  5. 用weexplus从0到1写一个app(2)-页面跳转和文章列表及文章详情的编写

    说明 结束连续几天的加班,最近的项目终于告一段落,今天抽点时间开始继续写我这篇拖了很久的<用weexplus从0到1写一个app>系列文章.写这篇文章的时候,weexplus的作者已经把w ...

  6. WP开发笔记——WP APP添加页面跳转动画

    微软的toolkit团队为我们为我们提供了这样一套组件,叫做TransitionServices服务. 简单说一下它具备的效果: turnstile(轴旋转效果): turnstile feather ...

  7. iOS app url scheme跳转到淘宝商品详情页 唤醒app

    最近涉及的一个业务,在app内的一个广告,点击打开webView,加载的是一个淘宝商品详情页,效果是打开该webView自动跳转至淘宝对应的页面,同时在自己的app仍然加载页面,点击评论等也同样能跳转 ...

  8. iOS从不同页面跳转回到指定控制器

    HomeViewController *homeVC = [[HomeViewController alloc] init]; UIViewController *target = nil; for ...

  9. iOS之safari调试iOS app web页面

    Overview 当下移动端开发过程中大量使用前段H5.js等等技术,而这些web页面的调试在Xcode控制台中不太明了,经常我们移动app运行了就是方法,但是不能显示响应的效果,这时候或许就是已经报 ...

随机推荐

  1. 说出x的结果,并解释为什么?

    var x = 1; if(function f(){}){ x += typeof f; } x; //x的结果是? x=1undefined 首先是 if表达式的问题 if括号里,不一定非要用== ...

  2. 【Chromium中文文档】Profile架构(看看谷歌家的重构)

    进程模型 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Profile_ ...

  3. vmware 使用技巧

    1.虚拟机如何进入BIOS界面? 方法: 1) 开机按F2 2) 若来不及按F2的话,可以通过以下 2. 如何让虚拟机进入安全模式? 方法:开机快速按F8 3. 当不能连接到vCenter Serve ...

  4. MySQL中用decimal的原因

    原因:float保存的值有可能是这个值的近似值,而不是这个值的真实值.如 0.1在二进制中是没有办法保存真实值的. 下面是例子: 第一步:建表: create table t2(x float,y d ...

  5. JAVA之Exchanger

    如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使用的空间,就需要用到Exchanger这个类,Exchanger为线程交换信息提供了非常方便的途径,它可以作为两个线程交换对象的同步点,只 ...

  6. 这才是正确删除 office 的方式

    https://support.office.com/zh-cn/article/%E9%80%9A%E8%BF%87%E5%9C%A8%E9%87%8D%E6%96%B0%E5%AE%89%E8%A ...

  7. cocos2d-x创建场景

    今天开始学习Cocos2d-x,使用的版本是2.1.4,这个版本比较老,对应的参考资料也比较齐全. 在mac/xcode环境下,代码是写在Classes文件夹下的,和iOS应用类似,程序从AppDel ...

  8. mac文件权限

    如何设置文件/或文件夹权限为777 进入终端,切换到指定目录,输入以下命令,后面添加你的文件名/目录名$sudo chmod -R 777 (文件名/目录名) 或 $chmod 777 ./test. ...

  9. 使用sphinx索引mysql数据

    数据库表如下 mysql> select * from tb_account; +----+-------+------+ | id | name | age | +----+-------+- ...

  10. Python入门-函数的使用到程序的公布安装

    Python入门-函数的使用到Python的公布安装 本文主要适合有一定编程经验,至少掌握一门编程语言的人查看. 文中样例大多都是简单到认识英文单词就能看懂的水平,主要讲的是Python的总体使用方法 ...