@@ -46,65 +46,20 @@ - (instancetype)init
4646}
4747- (void )show : (CDVInvokedUrlCommand*)command {
4848
49- CDVPluginResult * pluginResult;
49+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR] ;
5050
51- @try {
52-
53- NSString *viewControllerName;
54- NSString *storyboardName;
55- NSString *uri;
56- NSString *message;
57- NSString *firstParam;
51+ NSString * className = [command argumentAtIndex: 0 ];
52+ NSString * storyboardName = @" " ;
53+
54+ UIViewController *viewController = nil ;
55+
56+ if ([command.arguments count ] > 1 ) {
5857
59- NSMutableDictionary * config = [command.arguments objectAtIndex: 0 ];
58+ NSString * secondParam = [command argumentAtIndex: 1 ];
6059
61- if ([config isKindOfClass: [NSMutableDictionary class ]]) {
62-
63- viewControllerName = [config objectForKey: @" viewControllerName" ];
64- storyboardName = [config objectForKey: @" storyboardName" ];
65- uri = [config objectForKey: @" uri" ];
66-
67- } else if ([config isKindOfClass: [NSString class ]]) {
68-
69- if ([command.arguments count ] == 1 ) {
70-
71- firstParam = [command argumentAtIndex: 0 ];
72-
73- if ([self isValidURI: firstParam]) {
74- // Open app with valid uri name
75- [self openAPP: firstParam withCommand: command];
76-
77- } else if ([firstParam containsString: @" Storyboard" ]) {
78- // Init viewController from Storyboard with initial view Controller or user defined viewControllerName
79- [self instantiateViewController: nil fromStoryboard: firstParam];
80-
81- } else if ([firstParam containsString: @" Controller" ]) {
82- // Init viewController with or without xib
83- [self instantiateViewController: firstParam];
84-
85- } else {
86- message = [[NSString alloc ] initWithFormat: @" %@ invalid. Must contain a Storyboard / Controller / URI valid in name" , firstParam];
87- @throw [[NSException alloc ] initWithName: @" IoException" reason: message userInfo: nil ];
88- }
89-
90- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK];
91- return ;
92-
93- }else if ([command.arguments count ] == 2 ) {
94-
95- // first param is Storyboard
96- storyboardName = [command argumentAtIndex: 0 ];
97-
98- // second param is ViewController and/or storyboardId
99- viewControllerName = [command argumentAtIndex: 1 ];
100-
101- }else {
102- message = [[NSString alloc ] initWithFormat: @" An UIViewController name or Storyboard name or URI valid name is required at least. Please, pass in the first param in JS, like this: 'NativeView.show('MyViewController') or NativeView.show('MyStoryboard') or NativeView.show('MyStoryboard', 'MyViewController') or NativeView.show('instagram://')" ];
103- @throw [[NSException alloc ] initWithName: @" NotFoundException" reason: message userInfo: nil ];
104- }
105-
106- }else {
107- @throw [[NSException alloc ] initWithName: @" ParamsTypeException" reason: @" The params of show() method needs be a string or a json" userInfo: nil ];
60+ if (secondParam != nil ) {
61+ storyboardName = className;
62+ className = secondParam != nil ? secondParam : @" " ;
10863 }
10964
11065 if ([self isValidURI: uri]) {
@@ -136,236 +91,85 @@ - (void)show:(CDVInvokedUrlCommand*)command {
13691 pluginResult = [CDVPluginResult resultWithStatus: exceptionType messageAsDictionary: error];
13792 }
13893
139- [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
140- }
141-
142- - (void )showMarket : (CDVInvokedUrlCommand*)command {
143-
144- NSMutableDictionary * config = [command.arguments objectAtIndex: 0 ];
145-
146- dispatch_async (dispatch_get_main_queue (), ^{
94+ if ([self .viewController navigationController ] != nil ) {
14795
148- CDVPluginResult *pluginResult;
149- NSString *appId;
150-
151- if ([config isKindOfClass: [NSMutableDictionary class ]]) {
152- appId = [config objectForKey: @" marketId" ];
153- }else if ([config isKindOfClass: [NSString class ]]) {
154- appId = (NSString *) config;
155- }
156-
157- if (appId && [appId isKindOfClass: [NSString class ]] && [appId length ] > 0 ) {
158- NSString *url = [NSString stringWithFormat: @" itms://itunes.apple.com/app/%@ " , appId];
159-
160- [self openAPP: url withCommand: command];
96+ if ([self .viewController.navigationController.viewControllers count ] > 1 ) {
97+ [self .viewController.navigationController popViewControllerAnimated: YES ];
98+ }else {
16199
162- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK];
163- } else {
164- NSDictionary * error = @{
165- @" success" : @NO ,
166- @" name" : @" ParamInvalidException" ,
167- @" message" : @" Invalid application id: the parameter 'marketId' is invalid"
168- };
100+ viewController = [self instantiateViewControllerWithName: className];
169101
170- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_INVALID_ACTION messageAsDictionary: error ];
102+ [ self .viewController.navigationController pushViewController: viewController animated: YES ];
171103 }
172104
173- [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
174- });
175- }
176-
177- - (void )checkIfAppInstalled : (CDVInvokedUrlCommand*)command {
178- CDVPluginResult *pluginResult;
179- NSString *uri;
180-
181- @try {
182- NSMutableDictionary * config = [command.arguments objectAtIndex: 0 ];
105+ pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK];
183106
184- if ([config isKindOfClass: [NSMutableDictionary class ]]) {
185- uri = [config objectForKey: @" uri" ];
186-
187- if (uri == nil ) {
188- @throw [[NSException alloc ] initWithName: @" ParamsTypeException" reason: @" The 'uri' key is required" userInfo: nil ];
189- }
190- }else if ([config isKindOfClass: [NSString class ]]) {
191- uri = (NSString *) config;
192- }else {
193- @throw [[NSException alloc ] initWithName: @" ParamsTypeException" reason: @" The params of checkIfAppInstalled() method needs be a string or a json" userInfo: nil ];
194- }
107+ }else if (className.length > 0 ){
195108
196- if (![self isValidURI: uri]) {
197- NSString *message = [[NSString alloc ] initWithFormat: @" uri param invalid: %@ " , uri];
198- NSDictionary * error = @{
199- @" success" : @NO ,
200- @" name" : @" ParamInvalidException" ,
201- @" message" : message
202- };
109+ if ([[NSBundle mainBundle ] pathForResource: storyboardName ofType: @" storyboardc" ] != nil
110+ && storyboardName.length > 0 ) {
111+
112+ UIStoryboard* storyboard = [UIStoryboard storyboardWithName: storyboardName bundle: [NSBundle mainBundle ]];
203113
204- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: error];
205- } else {
206- if ([[UIApplication sharedApplication ] canOpenURL: [NSURL URLWithString: uri]]) {
207- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: (true )];
208- }
209- else {
210- NSString *message = [[NSString alloc ] initWithFormat: @" The app that responds to URI: %@ was not found" , uri];
211- NSDictionary * error = @{
212- @" success" : @NO ,
213- @" name" : @" NotFoundException" ,
214- @" message" : message
215- };
114+ viewController = [storyboard instantiateViewControllerWithIdentifier: className];
115+
116+ }else {
216117
217- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION messageAsDictionary: error ];
118+ viewController = [self tryInstantiateViewWithName: className ];
218119 }
219120 }
220121 } @catch (NSException *e) {
221122 NSLog (@" [%@ ]: %@ " , e.name , e.reason );
222123
223- typedef CDVCommandStatus (^CaseBlock)(void );
224-
225- CaseBlock c = self.resultExceptions [e.name];
226-
227- CDVCommandStatus exceptionType = c ? c () : CDVCommandStatus_ERROR;
228- NSDictionary * error = @{
229- @" success" : @NO ,
230- @" name" : e.name ,
231- @" message" : e.reason
232- };
233- pluginResult = [CDVPluginResult resultWithStatus: exceptionType messageAsDictionary: error];
234- } @finally {
235- [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
236- }
237- }
238-
239- - (void ) instantiateViewController : (NSString *)viewControllerName {
240-
241- NSString *message;
242-
243- if (viewControllerName && viewControllerName.length > 0 ) {
244-
245- UIViewController *destinyViewController = nil ;
124+ CDVAppDelegate* appDelegate = [[UIApplication sharedApplication ] delegate ];
125+ appDelegate.window .rootViewController = viewController;
246126
247- // Call preInitializeViewControllerWithName if exists in self.viewController
248- SEL selector = NSSelectorFromString (@" preInitializeViewControllerWithName:" );
249-
250- if ([self .viewController respondsToSelector: selector]) {
251-
252- SuppressPerformSelectorLeakWarning (
253- destinyViewController = [self .viewController performSelector: selector withObject: viewControllerName];
254- );
127+ pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK];
128+ }else {
129+ @try {
130+ [self raiseClassNameError ];
131+ } @catch (InstantiateViewControllerError* e) {
132+ NSLog (@" %@ " , e.reason );
255133 }
256-
257- // if not performSelector, call automatically the viewController
258- if (!destinyViewController) {
259- @try {
260- if ([[NSBundle mainBundle ] pathForResource: viewControllerName ofType: @" nib" ]) {
261- // Initialize with nib/xib
262- destinyViewController = [[UIViewController alloc ] initWithNibName: viewControllerName bundle: nil ];
263- } else {
264- // Initialize without nib/xib
265- Class viewController = NSClassFromString (viewControllerName);
266- id anInstance = [[viewController alloc ] init ];
267- destinyViewController = anInstance;
268- }
269- } @catch (NSException *e) {
270- message = [[NSString alloc ] initWithFormat: @" %@ and/or its own xib does not exist. \n Detail: %@ " , viewControllerName, e.reason];
271- @throw [[NSException alloc ] initWithName: @" NotFoundException" reason: message userInfo: nil ];
272- }
273- }
274-
275- // Call destinyViewController from current viewController
276- [self .viewController.navigationController pushViewController: destinyViewController animated: YES ];
277-
278- } else {
279- message = [[NSString alloc ] initWithFormat: @" UIViewController with name %@ was not found" , viewControllerName];
280- @throw [[NSException alloc ] initWithName: @" ParamInvalidException" reason: message userInfo: nil ];
281134 }
135+
136+ [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId ];
282137}
283138
284- - (void ) instantiateViewController : ( NSString *) viewControllerName fromStoryboard : (NSString *) storyboardName {
139+ - (UIViewController*) instantiateViewControllerWithName : (NSString *) name {
285140
286- NSString *message;
287-
288- if (storyboardName && storyboardName.length > 0 ) {
289-
290- UIViewController *destinyViewController = nil ;
141+ if ([[NSBundle mainBundle ] pathForResource: name ofType: @" nib" ]) {
142+ return [[UIViewController alloc ] initWithNibName: name bundle: nil ];
143+ }else {
291144
292- // Call preInitializeViewControllerWithName:fromStoryBoardName if exists in self.viewController
293- SEL selector = NSSelectorFromString ( @" preInitializeViewControllerWithName:fromStoryBoardName: " ) ;
145+ NSBundle * mainBundle = [ NSBundle mainBundle ];
146+ NSString *storyboardName = [mainBundle objectForInfoDictionaryKey: @" UIMainStoryboardFile " ] ;
294147
295- if ([self .viewController respondsToSelector: selector]) {
296-
297- SuppressPerformSelectorLeakWarning (
298- destinyViewController = [self .viewController performSelector: selector withObject: viewControllerName withObject: storyboardName];
299- );
148+ if (storyboardName != nil ) {
149+ UIStoryboard * storyboard = [UIStoryboard storyboardWithName: storyboardName bundle: nil ];
150+ return [storyboard instantiateViewControllerWithIdentifier: name];
300151 }
301-
302- // if not performSelector, call automatically the viewController from storyboard
303- if (!destinyViewController) {
304- // initialize a storyboard automatically from viewControllerName or default initialViewController property
305- @try {
306- UIStoryboard *storyboard = [UIStoryboard storyboardWithName: storyboardName bundle: [NSBundle mainBundle ]];
307-
308- if (viewControllerName && viewControllerName.length > 0 ) {
309- message = [[NSString alloc ] initWithFormat: @" Identity -> Storyboard ID: %@ not found in storyboard %@ " , viewControllerName, storyboardName];
310- // if pass a viewControllerName, initializate the storyboard with viewControllerName initial
311- destinyViewController = [storyboard instantiateViewControllerWithIdentifier: viewControllerName];
312- } else {
313- message = [[NSString alloc ] initWithFormat: @" Storyboard -> ViewController -> 'is Initial View Controller' not check in storyboard %@ " , storyboardName];
314- // if not pass a viewControllerName, initializate the storyboard with default inicialViewController property
315- destinyViewController = [storyboard instantiateInitialViewController ];
316- }
317- } @catch (NSException *e) {
318- NSString *detailMessage = [[NSString alloc ] initWithFormat: @" %@ \n Detail: %@ " , message, e.reason];
319- @throw [[NSException alloc ] initWithName: @" NotFoundException" reason: detailMessage userInfo: nil ];
320- }
321- }
322-
323- // Call destinyViewController from current viewController
324- [self .viewController.navigationController pushViewController: destinyViewController animated: YES ];
325-
326- } else {
327- message = [[NSString alloc ] initWithFormat: @" Storyboard %@ was not found" , storyboardName];
328- @throw [[NSException alloc ] initWithName: @" ParamInvalidException" reason: message userInfo: nil ];
329152 }
153+
154+ NSString * message = [[NSString alloc ] initWithFormat: @" The ViewController: %@ was not found" , name];
155+ @throw [[InstantiateViewControllerError alloc ] initWithName: @" notFound" reason: message userInfo: nil ];
330156}
331157
332- - (bool ) isValidURI : (NSString *)uri {
333- if (uri != nil && [uri containsString: @" ://" ]) { // TODO: Replace for regular expression
334- return true ;
158+ - (UIViewController*) tryInstantiateViewWithName : (NSString *)name {
159+
160+ @try {
161+ return [self instantiateViewControllerWithName: name];
162+ } @catch (InstantiateViewControllerError* e) {
163+ NSLog (@" %@ " , e.reason );
335164 }
336- return false ;
165+
166+ return nil ;
337167}
338168
339- - (void ) openAPP : ( NSString *) uriValue withCommand : (CDVInvokedUrlCommand*) command {
169+ - (void ) raiseClassNameError {
340170
341- if ([[UIApplication sharedApplication ] respondsToSelector: @selector (openURL:options:completionHandler: )]) { // ios >= 10
342- [[UIApplication sharedApplication ] openURL: [NSURL URLWithString: uriValue] options: @{} completionHandler: ^(BOOL opened) {
343-
344- CDVPluginResult *pluginResult;
345-
346- if (!opened) {
347- NSString * message = @" APP with uri %@ not found." ;
348- NSLog (message, uriValue);
349-
350- NSDictionary * error = @{
351- @" success" : @NO ,
352- @" name" : @" InstantiationException" ,
353- @" message" : [[NSString alloc ] initWithFormat: message, uriValue]
354- };
355-
356- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_INSTANTIATION_EXCEPTION messageAsDictionary: error];
357- } else {
358- NSString * message = @" APP with uri %@ opened." ;
359- NSLog (message, uriValue);
360-
361- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsString: [[NSString alloc ] initWithFormat: message, uriValue]];
362- }
363-
364- [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
365- }];
366- } else { // ios < 10 (Will be depreciated)
367- [[UIApplication sharedApplication ] openURL: [NSURL URLWithString: uriValue]];
368- }
171+ NSString * message = [[NSString alloc ] initWithFormat: @" The UIViewController name is required when the project don't have a navigatioController. Please, pass a className by param in JS, like this: 'NativeView.show('MyUIViewController')" ];
172+ @throw [[InstantiateViewControllerError alloc ] initWithName: @" nameNotDefined" reason: message userInfo: nil ];
369173}
370174
371175@end
0 commit comments