diff --git a/AMAppExportToIPA/NSObject+MethodSwizzler.h b/AMAppExportToIPA/NSObject+MethodSwizzler.h index fd8f292..89adae2 100644 --- a/AMAppExportToIPA/NSObject+MethodSwizzler.h +++ b/AMAppExportToIPA/NSObject+MethodSwizzler.h @@ -8,7 +8,7 @@ @interface NSObject (MethodSwizzler) -+ (void)swizzleWithOriginalSelector:(SEL)originalSelector ++ (void)am_swizzleWithOriginalSelector:(SEL)originalSelector swizzledSelector:(SEL) swizzledSelector isClassMethod:(BOOL)isClassMethod; diff --git a/AMAppExportToIPA/NSObject+MethodSwizzler.m b/AMAppExportToIPA/NSObject+MethodSwizzler.m index b34df49..ba90773 100644 --- a/AMAppExportToIPA/NSObject+MethodSwizzler.m +++ b/AMAppExportToIPA/NSObject+MethodSwizzler.m @@ -10,7 +10,7 @@ @implementation NSObject (MethodSwizzler) -+ (void)swizzleWithOriginalSelector:(SEL)originalSelector ++ (void)am_swizzleWithOriginalSelector:(SEL)originalSelector swizzledSelector:(SEL) swizzledSelector isClassMethod:(BOOL)isClassMethod { diff --git a/AMAppExportToIPA/NSObject+PopupMenu.h b/AMAppExportToIPA/NSObject+PopupMenu.h index 7adec5f..5b4dedf 100644 --- a/AMAppExportToIPA/NSObject+PopupMenu.h +++ b/AMAppExportToIPA/NSObject+PopupMenu.h @@ -8,6 +8,6 @@ #import "RuntimeHeaders.h" #import -@interface NSObject (AM_PopupMenu) +@interface NSMenu (AM_PopupMenu) @end diff --git a/AMAppExportToIPA/NSObject+PopupMenu.m b/AMAppExportToIPA/NSObject+PopupMenu.m index 971d44e..1725322 100644 --- a/AMAppExportToIPA/NSObject+PopupMenu.m +++ b/AMAppExportToIPA/NSObject+PopupMenu.m @@ -9,6 +9,13 @@ #import "NSObject+MethodSwizzler.h" #import #import +#import + +NSString *const kAMProjectNavigatorContextualMenu = @"Project navigator contextual menu"; +NSString *const kAMExportIPA = @"Export IPA"; +//NSString *const kAMFilePath = @"AMFilePath"; + +static void *kAMFilePath; @interface NSObject () @@ -17,7 +24,7 @@ - (void)_popUpContextMenu:(id)arg1 withEvent:(id)arg2 forView:(id)arg3 withFont: @end -@implementation NSObject (AM_PopupMenu) +@implementation NSMenu (AM_PopupMenu) + (void)load { @@ -25,52 +32,74 @@ + (void)load dispatch_once(&onceToken, ^{ - [NSClassFromString(@"NSMenu") swizzleWithOriginalSelector:@selector(_popUpContextMenu:withEvent:forView:withFont:) swizzledSelector:@selector(AM_popUpContextMenu:withEvent:forView:withFont:) isClassMethod:NO]; + [NSClassFromString(@"NSMenu") am_swizzleWithOriginalSelector:@selector(_popUpContextMenu:withEvent:forView:withFont:) swizzledSelector:@selector(am_popUpContextMenu:withEvent:forView:withFont:) isClassMethod:NO]; - [NSClassFromString(@"NSMenu") swizzleWithOriginalSelector:@selector(addItem:) swizzledSelector:@selector(AM_addItem:) isClassMethod:NO]; + [NSClassFromString(@"NSMenu") am_swizzleWithOriginalSelector:@selector(addItem:) swizzledSelector:@selector(am_addItem:) isClassMethod:NO]; }); } -//Project Navigator Help -- (void)AM_addItem:(NSMenuItem *)item +- (NSString *)am_filePath { + NSString *result = objc_getAssociatedObject(self, &kAMFilePath); + return result; +} +- (void)set_am_filePath:(NSString *)filePath { + objc_setAssociatedObject(self, &kAMFilePath, filePath, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + + +//Method call flow: +// Init menu: popUpContextMenu:withEvent:forView:withFont: > addItem: +// Menu exist: popUpContextMenu:withEvent:forView:withFont: +//Project navigator contextual menu +- (void)am_addItem:(NSMenuItem *)item { - [self AM_addItem:item]; - NSString *filePath = [[NSUserDefaults standardUserDefaults] objectForKey:@"AMFilePath"]; - - NSString *title = @"Export IPA"; - if ([[item title] isEqualToString:@"Project Navigator Help"]) { - NSMenu *menu = item.menu; - if ([menu itemWithTitle:title] != nil) { - [menu removeItem:[menu itemWithTitle:title]]; - } - SEL selector = [filePath.pathExtension isEqualToString:@"app"]? @selector(generateIPA:):nil; - NSMenuItem *actionMenuItem = [[NSMenuItem alloc] initWithTitle:title action:selector keyEquivalent:@""]; - [menu addItem:actionMenuItem]; - actionMenuItem.target = self; - + [self am_addItem:item]; + if ([self.title isEqualToString:kAMProjectNavigatorContextualMenu]) { + [self addExportIPAMenuItemWithMenu:item.menu]; } + } -- (void)AM_popUpContextMenu:(NSMenu *)arg1 withEvent:(NSEvent *)arg2 forView:(NSView *)arg3 withFont:(id)arg4 +- (void)am_popUpContextMenu:(NSMenu *)arg1 withEvent:(NSEvent *)arg2 forView:(NSView *)arg3 withFont:(id)arg4 { - if ([arg3 isKindOfClass:NSClassFromString(@"IDENavigatorOutlineView")]) { - [arg1 removeAllItems]; + IDENavigatorOutlineView *view = (IDENavigatorOutlineView *)arg3; NSArray *select = [view contextMenuSelectedItems]; - if ([select.firstObject respondsToSelector:@selector(fileURL)]) { - [[NSUserDefaults standardUserDefaults] setObject:select.firstObject.fileURL.absoluteString forKey:@"AMFilePath"]; + if ([select.firstObject respondsToSelector:@selector(fileURL)] && [select.firstObject.fileURL.absoluteString.pathExtension isEqualToString:@"app"]) { + [self set_am_filePath:select.firstObject.fileURL.absoluteString]; }else { - [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"AMFilePath"]; + [self set_am_filePath:@""]; + } + //If menu exist, then update menu status. + if ([self.title isEqualToString:kAMProjectNavigatorContextualMenu]) { + [self addExportIPAMenuItemWithMenu:arg1]; } - } - [self AM_popUpContextMenu:arg1 withEvent:arg2 forView:arg3 withFont:arg4]; + [self am_popUpContextMenu:arg1 withEvent:arg2 forView:arg3 withFont:arg4]; + +} + +- (void)addExportIPAMenuItemWithMenu:(NSMenu *)menu +{ + NSString *filePath = [self am_filePath]; + + NSMenuItem *item = [menu itemWithTitle:kAMExportIPA]; + if (item != nil) { + [menu removeItem:item]; + } + + SEL selector = [filePath.pathExtension isEqualToString:@"app"] ? @selector(generateIPA:): nil; + NSMenuItem *actionMenuItem = [[NSMenuItem alloc] initWithTitle:kAMExportIPA action:selector keyEquivalent:@""]; + [menu am_addItem:actionMenuItem]; + actionMenuItem.enabled = [filePath.pathExtension isEqualToString:@"app"]; + actionMenuItem.target = self; + } - (void)generateIPA:(id)arg1 { - NSString *filePath = [[NSUserDefaults standardUserDefaults] objectForKey:@"AMFilePath"]; + NSString *filePath = [self am_filePath]; //Trim file url string. filePath = [filePath stringByReplacingOccurrencesOfString:@"file://" withString:@""]; @@ -81,7 +110,10 @@ - (void)generateIPA:(id)arg1 { NSString *dateString = [dateFormatter stringFromDate:[NSDate date]]; NSString *fileName = [filePath.lastPathComponent substringWithRange:NSMakeRange(0, filePath.lastPathComponent.length-4)]; - NSString *commands = [NSString stringWithFormat:@"mkdir ~/Desktop/AM_Builds;xcrun -sdk iphoneos PackageApplication -v \"%@\" -o ~/Desktop/AM_Builds/%@-%@.ipa;open ~/Desktop/AM_Builds/", [self URLDecode:filePath], [[self URLDecode:fileName] stringByReplacingOccurrencesOfString:@" " withString:@"-"], dateString]; + NSString *commands = [NSString stringWithFormat:@"mkdir ~/Desktop/AM_Builds;xcrun -sdk iphoneos PackageApplication -v \"%@\" -o ~/Desktop/AM_Builds/%@-%@.ipa;open ~/Desktop/AM_Builds/", + [self URLDecode:filePath], + [[self URLDecode:fileName] stringByReplacingOccurrencesOfString:@" " withString:@"-"], + dateString]; //Excute shell task NSTask *task = [[NSTask alloc] init];