10 |
11 | @implementation NSObject (MethodSwizzler)
12 |
13 | + (void)am_swizzleWithOriginalSelector:(SEL)originalSelector
14 | swizzledSelector:(SEL) swizzledSelector
15 | isClassMethod:(BOOL)isClassMethod
16 | {
17 | Class cls = [self class];
18 |
19 | Method originalMethod;
20 | Method swizzledMethod;
21 |
22 | if (isClassMethod) {
23 | originalMethod = class_getClassMethod(cls, originalSelector);
24 | swizzledMethod = class_getClassMethod(cls, swizzledSelector);
25 | } else {
26 | originalMethod = class_getInstanceMethod(cls, originalSelector);
27 | swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
28 | }
29 |
30 | if (!originalMethod) {
31 | NSLog(@"Error: originalMethod is nil, did you spell it incorrectly? %@", originalMethod);
32 | return;
33 | }
34 |
35 | method_exchangeImplementations(originalMethod, swizzledMethod);
36 | }
37 | @end
38 |
--------------------------------------------------------------------------------
/AMAppExportToIPA/AMAppExportToIPAXcodePlugin.m:
--------------------------------------------------------------------------------
1 | //
2 | // AMAppExportToIPAXcodePlugin.m
3 | // AMAppExportToIPAXcodePlugin
4 | //
5 | // Created by Mellong on 16/2/16.
6 | // Copyright © 2016年 Tendencystudio. All rights reserved.
7 | //
8 |
9 | #import "AMAppExportToIPAXcodePlugin.h"
10 |
11 | @interface AMAppExportToIPAXcodePlugin()
12 |
13 | @property (nonatomic, strong, readwrite) NSBundle *bundle;
14 | @end
15 |
16 | @implementation AMAppExportToIPAXcodePlugin
17 |
18 | + (instancetype)sharedPlugin
19 | {
20 | return sharedPlugin;
21 | }
22 |
23 | - (id)initWithBundle:(NSBundle *)plugin
24 | {
25 | if (self = [super init]) {
26 | // reference to plugin's bundle, for resource access
27 | self.bundle = plugin;
28 | [[NSNotificationCenter defaultCenter] addObserver:self
29 | selector:@selector(didApplicationFinishLaunchingNotification:)
30 | name:NSApplicationDidFinishLaunchingNotification
31 | object:nil];
32 | }
33 | return self;
34 | }
35 |
36 | - (void)didApplicationFinishLaunchingNotification:(NSNotification*)noti
37 | {
38 | //removeObserver
39 | [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:nil];
40 | }
41 |
42 | - (void)dealloc
43 | {
44 | [[NSNotificationCenter defaultCenter] removeObserver:self];
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/AMAppExportToIPA/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | BNDL
19 | CFBundleShortVersionString
20 | 1.2
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.2
25 | DVTPlugInCompatibilityUUIDs
26 |
27 | C4A681B0-4A26-480E-93EC-1218098B9AA0
28 | F41BD31E-2683-44B8-AE7F-5F09E919790E
29 | AD68E85B-441B-4301-B564-A45E4919A6AD
30 | A16FF353-8441-459E-A50C-B071F53F51B7
31 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7
32 | E969541F-E6F9-4D25-8158-72DC3545A6C6
33 | 8DC44374-2B35-4C57-A6FE-2AD66A36AAD9
34 | AABB7188-E14E-4433-AD3B-5CD791EAD9A3
35 | 8DC44374-2B35-4C57-A6FE-2AD66A36AAD9
36 | AABB7188-E14E-4433-AD3B-5CD791EAD9A3
37 | 7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90
38 | 0420B86A-AA43-4792-9ED0-6FE0F2B16A13
39 | 7265231C-39B4-402C-89E1-16167C4CC990
40 | ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C
41 |
42 | LSMinimumSystemVersion
43 | $(MACOSX_DEPLOYMENT_TARGET)
44 | NSPrincipalClass
45 | AMAppExportToIPAXcodePlugin
46 | XC4Compatible
47 |
48 | XCPluginHasUI
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/AMAppExportToIPA.xcodeproj/xcshareddata/xcschemes/AMAppExportToIPA.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
46 |
49 |
50 |
51 |
57 |
58 |
59 |
60 |
61 |
62 |
68 |
69 |
75 |
76 |
77 |
78 |
80 |
81 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Donate
2 | ===========
3 |
4 | * [Donate via paypal](https://paypal.me/mellonglau)
5 |
6 | AMAppExportToIPA-Xcode-Plugin
7 | ==================
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | AMAppExportToIPA is a simple Xcode plugin to export `.app` to `.ipa` file.
18 |
19 | **Note:** Please update to v1.1 in order to avoid conflicts with other plug-ins.
20 |
21 | **Clicked Export to IPA without any response in Xcode 8.3+?**
22 | This is because Xcode 8.3 have removed PackageApplication, you can copy this component from the earlier Xcode, the following link is the detail of this temporary fix:
23 | [www.jianshu.com/p/88bb51cba34d](www.jianshu.com/p/88bb51cba34d)
24 |
25 | > *AMAppExportToIPA 是一款可以让你在Xcode的project navigator界面中直接右键点击xxx.app -> Export IPA就可以生成对应的IPA文件的Xcode插件。*
26 |
27 | > **注意:** 请更新到v1.1以避免和其他Xcode插件冲突。
28 |
29 | **Xcode8.3+可能会点击生成IPA没有任何反应,这是因为Xcode 8.3已经移除了 PackageApplication,你可以自行从旧版本的Xcode拷贝这个插件,具体方法请参考: [http://www.jianshu.com/p/88bb51cba34d](http://www.jianshu.com/p/88bb51cba34d)**
30 |
31 | > **如果觉得这款插件不错的话请点击右上角的star和推荐给你的朋友,如果想即时了解到我的最新消息,请拉到底部扫描二维码关注我的公众号**
32 |
33 | Welcome to join in QQ group 5522740 for further discussion.
34 | 欢迎加入QQ群 5522740 交流iOS开发.
35 |
36 | ## Usage
37 |
38 | 
39 |
40 | ## Install
41 |
42 | You can:
43 |
44 | Install from github.
45 |
46 | * Get the source code from github
47 |
48 | `$ git clone git@github.com:MellongLau/AMAppExportToIPA-Xcode-Plugin.git`
49 |
50 | * Build the AMAppExportToIPA target in the Xcode project and the plug-in will automatically be installed in `~/Library/Application Support/Developer/Shared/Xcode/Plug-ins`.
51 | * Relaunch Xcode.
52 |
53 | or
54 |
55 | Install via [Alcatraz](http://alcatraz.io/)
56 |
57 | In any case, relaunch Xcode to load it.
58 |
59 |
60 | ## Support
61 |
62 | Developed and tested against Xcode 6+.
63 |
64 | After upgrade your Xcode, you may need to run below shell script to add your current Xcode DVTPlugInCompatibilityUUID to all the Xcode plugins:
65 |
66 | > curl https://raw.githubusercontent.com/cielpy/RPAXU/master/refreshPluginsAfterXcodeUpgrading.sh | sh
67 |
68 |
69 | ## More
70 | Learn more? Follow my `WeChat` public account `mellong`:
71 |
72 | 
73 |
74 | ## License
75 |
76 | MIT License
77 |
78 | Copyright (c) 2016 Mellong Lau
79 |
80 | Permission is hereby granted, free of charge, to any person obtaining a copy
81 | of this software and associated documentation files (the "Software"), to deal
82 | in the Software without restriction, including without limitation the rights
83 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84 | copies of the Software, and to permit persons to whom the Software is
85 | furnished to do so, subject to the following conditions:
86 |
87 | The above copyright notice and this permission notice shall be included in all
88 | copies or substantial portions of the Software.
89 |
90 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
93 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
95 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
96 | SOFTWARE.
97 |
--------------------------------------------------------------------------------
/AMAppExportToIPA/RuntimeHeaders.h:
--------------------------------------------------------------------------------
1 | //
2 | // RuntimeHeaders.h
3 | // AMAppExportToIPA-Xcode-Plugin
4 | //
5 | // Created by Mellong on 16/2/16.
6 | // Copyright © 2016年 Tendencystudio. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 |
13 | @class DVTFileDataType, NSColor, NSString, NSURL;
14 |
15 | @interface IDENavigableItem : NSObject
16 | @property (readonly) IDENavigableItem *parentItem;
17 | @property (readonly) id representedObject;
18 | @end
19 |
20 | @interface IDEFileNavigableItem : IDENavigableItem
21 | @property (readonly) DVTFileDataType *documentType;
22 | @property (readonly) NSURL *fileURL;
23 | @end
24 |
25 | @interface IDEFileReferenceNavigableItem : IDEFileNavigableItem
26 |
27 | + (id)_createExtraInfoObject;
28 | + (void)editorDocumentDirtyStatusDidChange:(id)arg1;
29 | + (void)initialize;
30 | + (id)keyPathsForValuesAffectingToolTip;
31 | - (unsigned long long)conflictStateForUpdateOrMerge;
32 | - (id)contentDocumentLocation;
33 | - (id)documentType;
34 | - (id)fileReference;
35 | - (NSURL *)fileURL;
36 | - (id)initWithRepresentedObject:(id)arg1;
37 | - (id)name;
38 | - (id)newImage;
39 | - (id)sourceControlCurrentRevision;
40 | - (id)sourceControlLocalStatus;
41 | - (int)sourceControlLocalStatusFlag;
42 | - (id)sourceControlServerStatus;
43 | - (int)sourceControlServerStatusFlag;
44 | @property(readonly) NSColor *textColor;
45 | - (id)toolTip;
46 | - (void)updateAttributes;
47 | - (void)updateChildRepresentedObjects;
48 |
49 | @end
50 |
51 | @class DVTMapTable, NSArray, NSEvent, NSIndexSet, NSString, NSTextField, NSTextFieldCell, NSTrackingArea;
52 |
53 | @protocol DVTProgressIndicatorProvidingView;
54 |
55 | @interface DVTOutlineView : NSOutlineView
56 | @property(retain) NSEvent *event; // @synthesize event=_event;
57 | @property BOOL skipGridLinesOnCollapsedGroupRows; // @synthesize skipGridLinesOnCollapsedGroupRows=_skipGridLinesOnCollapsedGroupRows;
58 | @property BOOL skipGridLinesOnLastRow; // @synthesize skipGridLinesOnLastRow=_skipGridLinesOnLastRow;
59 | @property(retain) id itemUnderHoveredMouse; // @synthesize itemUnderHoveredMouse=_itemUnderHoveredMouse;
60 | @property int indentationStyle; // @synthesize indentationStyle=_indentationStyle;
61 | @property int dvt_groupRowStyle; // @synthesize dvt_groupRowStyle=_dvt_groupRowStyle;
62 | @property(nonatomic) long long maxAlternatingRowBackgroundLevelInGroupRow; // @synthesize maxAlternatingRowBackgroundLevelInGroupRow=_maxAlternatingRowBackgroundLevelInGroupRow;
63 | @property(nonatomic) BOOL groupRowBreaksAlternatingRowBackgroundCycle; // @synthesize groupRowBreaksAlternatingRowBackgroundCycle=_groupRowBreaksAlternatingRowBackgroundCycle;
64 | @property(copy) NSIndexSet *draggedRows; // @synthesize draggedRows=_draggedRows;
65 | @property int emptyContentStringStyle; // @synthesize emptyContentStringStyle=_emptyContentStringStyle;
66 | @property(copy, nonatomic) NSString *emptyContentSubtitle; // @synthesize emptyContentSubtitle=_emptyContentSubtitle;
67 | @property(copy, nonatomic) NSString *emptyContentString; // @synthesize emptyContentString=_emptyContentString;
68 | - (unsigned long long)draggingSourceOperationMaskForLocal:(BOOL)arg1;
69 | - (void)setDraggingSourceOperationMask:(unsigned long long)arg1 forLocal:(BOOL)arg2;
70 | - (id)dragImageForRowsWithIndexes:(id)arg1 tableColumns:(id)arg2 event:(id)arg3 offset:(struct CGPoint *)arg4;
71 | - (void)concludeDragOperation:(id)arg1;
72 | - (void)draggingEnded:(id)arg1;
73 | - (unsigned long long)draggingUpdated:(id)arg1;
74 | - (unsigned long long)draggingEntered:(id)arg1;
75 | - (void)mouseExited:(id)arg1;
76 | - (void)mouseMoved:(id)arg1;
77 | - (void)delayedProcessMouseMovedEvent;
78 | - (void)restartMouseHoverTimer;
79 | - (void)invalidateMouseHoverTimer;
80 | - (void)updateDisplayOfItemUnderMouse:(id)arg1;
81 | - (void)setItemUnderMouseAndMarkForRedisplay:(id)arg1;
82 | - (void)updateTrackingAreas;
83 | @property BOOL revealsOutlineCellUnderHoveredMouseAfterDelay;
84 | - (void)viewWillMoveToWindow:(id)arg1;
85 | - (void)insertText:(id)arg1;
86 | - (void)doCommandBySelector:(SEL)arg1;
87 | - (void)keyDown:(id)arg1;
88 | - (void)viewWillMoveToSuperview:(id)arg1;
89 | - (void)viewWillDraw;
90 | - (BOOL)_shouldRemoveProgressIndicator:(id)arg1 forItem:(id)arg2 andVisibleRect:(struct CGRect)arg3;
91 | - (void)_showEmptyContentSublabel;
92 | - (void)_hideEmptyContentSublabel;
93 | - (void)_showEmptyContentLabel;
94 | - (void)_hideEmptyContentLabel;
95 | - (id)preparedCellAtColumn:(long long)arg1 row:(long long)arg2;
96 | - (Class)groupRowCellClassForDataCell:(id)arg1;
97 | - (id)_dataCellForGroupRowWithClass:(Class)arg1;
98 | - (id)groupRowFont;
99 | - (void)_drawRowHeaderSeparatorInClipRect:(struct CGRect)arg1;
100 | - (void)drawGridInClipRect:(struct CGRect)arg1;
101 | - (void)_drawBackgroundForGroupRow:(long long)arg1 clipRect:(struct CGRect)arg2 isButtedUpRow:(BOOL)arg3;
102 | - (void)drawBackgroundInClipRect:(struct CGRect)arg1;
103 | - (struct CGRect)frameOfOutlineCellAtRow:(long long)arg1;
104 | - (struct CGRect)frameOfCellAtColumn:(long long)arg1 row:(long long)arg2;
105 | @property(readonly) NSArray *contextMenuSelectedItems;
106 | @property(retain) NSArray *selectedItems;
107 | - (id)_itemsAtIndexes:(id)arg1;
108 | @property(readonly) NSIndexSet *contextMenuSelectedRowIndexes;
109 | @property(readonly) NSIndexSet *clickedRowIndexes;
110 | - (void)setSortDescriptors:(id)arg1;
111 | - (struct CGSize)_adjustFrameSizeToFitSuperview:(struct CGSize)arg1;
112 | @property BOOL allowsSizingShorterThanClipView;
113 | @property BOOL breaksCyclicSortDescriptors;
114 | - (id)progressIndicatorForItem:(id)arg1 createIfNecessary:(BOOL)arg2 progressIndicatorStyle:(unsigned long long)arg3;
115 | - (void)clearProgressIndicators;
116 | - (void)setDelegate:(id)arg1;
117 | - (id)initWithCoder:(id)arg1;
118 | - (id)initWithFrame:(struct CGRect)arg1;
119 | - (void)dvt_commonInit;
120 |
121 | @end
122 |
123 | @class DVTDelayedInvocation, DVTStackBacktrace, IDEOutlineViewGroupInfo, NSArray, NSHashTable, NSMutableIndexSet, NSPredicate, NSString, _IDENavigatorOutlineViewDataSource;
124 |
125 |
126 | @protocol DVTInvalidation;
127 |
128 | @interface IDENavigatorOutlineView : DVTOutlineView
129 |
130 | @end
131 |
--------------------------------------------------------------------------------
/AMAppExportToIPA/NSObject+PopupMenu.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+PopupMenu.m
3 | //
4 | // Created by Mellong on 16/2/15.
5 | // Copyright © 2016年 Tendencystudio. All rights reserved.
6 | //
7 |
8 | #import "NSObject+PopupMenu.h"
9 | #import "NSObject+MethodSwizzler.h"
10 | #import
11 | #import
12 | #import
13 |
14 | NSString *const kAMProjectNavigatorContextualMenu = @"Project navigator contextual menu";
15 | NSString *const kAMExportIPA = @"Export IPA";
16 |
17 | static void *kAMFilePath;
18 | static void *kAMBuildTask;
19 |
20 | @interface NSObject ()
21 |
22 | @property (nonatomic, copy) NSString *am_filePath;
23 | @property (nonatomic, strong) __block NSTask *am_buildTask;
24 |
25 |
26 | - (void)addItem:(id)item;
27 | - (void)_popUpContextMenu:(id)arg1 withEvent:(id)arg2 forView:(id)arg3 withFont:(id)arg4;
28 |
29 | @end
30 |
31 | @implementation NSMenu (AM_PopupMenu)
32 |
33 | + (void)load
34 | {
35 | static dispatch_once_t onceToken;
36 |
37 | dispatch_once(&onceToken, ^{
38 |
39 | [NSClassFromString(@"NSMenu") am_swizzleWithOriginalSelector:@selector(_popUpContextMenu:withEvent:forView:withFont:) swizzledSelector:@selector(am_popUpContextMenu:withEvent:forView:withFont:) isClassMethod:NO];
40 |
41 | [NSClassFromString(@"NSMenu") am_swizzleWithOriginalSelector:@selector(addItem:) swizzledSelector:@selector(am_addItem:) isClassMethod:NO];
42 | });
43 | }
44 |
45 | - (NSString *)am_filePath {
46 | NSString *result = objc_getAssociatedObject(self, &kAMFilePath);
47 | return result;
48 | }
49 |
50 | - (void)setAm_filePath:(NSString *)am_filePath {
51 | objc_setAssociatedObject(self, &kAMFilePath, am_filePath, OBJC_ASSOCIATION_COPY_NONATOMIC);
52 | }
53 |
54 | - (NSTask *)am_buildTask {
55 | NSTask *result = objc_getAssociatedObject(self, &kAMBuildTask);
56 | return result;
57 | }
58 |
59 | - (void)setAm_buildTask:(NSTask *)am_buildTask {
60 | objc_setAssociatedObject(self, &kAMBuildTask, am_buildTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
61 | }
62 |
63 | //Method call flow:
64 | // Init menu: popUpContextMenu:withEvent:forView:withFont: > addItem:
65 | // Menu exist: popUpContextMenu:withEvent:forView:withFont:
66 | //Project navigator contextual menu
67 | - (void)am_addItem:(NSMenuItem *)item
68 | {
69 | [self am_addItem:item];
70 | if ([self.title isEqualToString:kAMProjectNavigatorContextualMenu]) {
71 | [self addExportIPAMenuItemWithMenu:item.menu];
72 | }
73 |
74 | }
75 |
76 | - (void)am_popUpContextMenu:(NSMenu *)arg1 withEvent:(NSEvent *)arg2 forView:(NSView *)arg3 withFont:(id)arg4
77 | {
78 |
79 | if ([arg3 isKindOfClass:NSClassFromString(@"IDENavigatorOutlineView")]) {
80 |
81 | IDENavigatorOutlineView *view = (IDENavigatorOutlineView *)arg3;
82 | NSArray *select = [view contextMenuSelectedItems];
83 | if ([select.firstObject respondsToSelector:@selector(fileURL)] && [select.firstObject.fileURL.absoluteString.pathExtension isEqualToString:@"app"]) {
84 | [self setAm_filePath:select.firstObject.fileURL.absoluteString];
85 | }else {
86 | [self setAm_filePath:@""];
87 | }
88 | //If menu exist, then update menu status.
89 | if ([self.title isEqualToString:kAMProjectNavigatorContextualMenu] && arg1.itemArray.count > 0 ) {
90 | [self addExportIPAMenuItemWithMenu:arg1];
91 | }
92 | }
93 |
94 | [self am_popUpContextMenu:arg1 withEvent:arg2 forView:arg3 withFont:arg4];
95 | }
96 |
97 | - (void)addExportIPAMenuItemWithMenu:(NSMenu *)menu
98 | {
99 | NSString *filePath = [self am_filePath];
100 |
101 | NSMenuItem *item = [menu itemWithTitle:kAMExportIPA];
102 | if (item != nil) {
103 | [menu removeItem:item];
104 | }
105 |
106 | SEL selector = [filePath.pathExtension isEqualToString:@"app"] ? @selector(generateIPA:): nil;
107 | NSMenuItem *actionMenuItem = [[NSMenuItem alloc] initWithTitle:kAMExportIPA action:selector keyEquivalent:@""];
108 | [menu am_addItem:actionMenuItem];
109 | actionMenuItem.enabled = [filePath.pathExtension isEqualToString:@"app"];
110 | actionMenuItem.target = self;
111 |
112 | }
113 |
114 | - (void)generateIPA:(id)arg1 {
115 |
116 | NSProgressIndicator* indicator = [[NSProgressIndicator alloc] init];
117 | [indicator setStyle:NSProgressIndicatorSpinningStyle];
118 | NSWindowController *currentWindowController = [[NSApp keyWindow] windowController];
119 | if ([currentWindowController isKindOfClass:NSClassFromString(@"IDEWorkspaceWindowController")]) {
120 | [currentWindowController.window.contentView addSubview:indicator];
121 | [indicator setFrame:NSMakeRect(currentWindowController.window.contentView.frame.size.width/2.0, currentWindowController.window.contentView.frame.size.height/2.0, 30, 30)];
122 | [indicator startAnimation:self];
123 | }
124 |
125 | dispatch_queue_t taskQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
126 | dispatch_async(taskQueue, ^{
127 | int status = 0;
128 | @try {
129 | NSString *filePath = self.am_filePath;
130 |
131 | //Trim file url string.
132 | filePath = [filePath stringByReplacingOccurrencesOfString:@"file://" withString:@""];
133 | filePath = [filePath stringByReplacingOccurrencesOfString:@"/" withString:@"" options:0 range:NSMakeRange(filePath.length-2, 2)];
134 |
135 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
136 | [dateFormatter setDateFormat:@"yyyyMMdd-HHmmss"];
137 | NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
138 |
139 | NSString *fileName = [filePath.lastPathComponent substringWithRange:NSMakeRange(0, filePath.lastPathComponent.length-4)];
140 | NSString *decodeFilePath = [self URLDecode:filePath];
141 | NSString *targetFileName = [[self URLDecode:fileName] stringByReplacingOccurrencesOfString:@" " withString:@"-"];
142 |
143 | NSString *targetFilePath = [NSString stringWithFormat:@"~/Desktop/AM_Builds/%@-%@.ipa", targetFileName, dateString];
144 | NSString *commands = [NSString stringWithFormat:@"mkdir ~/Desktop/AM_Builds;xcrun -sdk iphoneos PackageApplication -v \"%@\" -o %@;open -R %@",
145 | decodeFilePath,
146 | targetFilePath,
147 | targetFilePath];
148 |
149 | //Excute shell task
150 | self.am_buildTask = [[NSTask alloc] init];
151 | [self.am_buildTask setLaunchPath:@"/bin/bash"];
152 | [self.am_buildTask setArguments:@[ @"-c", commands]];
153 | [self.am_buildTask launch];
154 | [self.am_buildTask waitUntilExit];
155 |
156 | //Launch result
157 | status = [self.am_buildTask terminationStatus];
158 |
159 |
160 | }@catch (NSException *exception) {
161 | NSLog(@"Problem Running Task: %@", [exception description]);
162 | }
163 | @finally {
164 | dispatch_async(dispatch_get_main_queue(), ^{
165 |
166 | [indicator stopAnimation:self];
167 | [indicator removeFromSuperview];
168 | });
169 |
170 | if (status == 0) {
171 | NSLog(@"Task succeeded.");
172 | }
173 | else {
174 | NSLog(@"Task failed.");
175 | }
176 | }
177 | });
178 | }
179 |
180 | - (NSString *)URLDecode:(NSString *)stringToDecode
181 | {
182 | NSString *result = [stringToDecode stringByReplacingOccurrencesOfString:@"+" withString:@" "];
183 | result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
184 | return result;
185 | }
186 |
187 | @end
188 |
--------------------------------------------------------------------------------
/AMAppExportToIPA.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 242F77671C730DCF005EFFA4 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 242F77661C730DCF005EFFA4 /* AppKit.framework */; };
11 | 242F77691C730DCF005EFFA4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 242F77681C730DCF005EFFA4 /* Foundation.framework */; };
12 | 242F776D1C730DCF005EFFA4 /* AMAppExportToIPA.xcscheme in Resources */ = {isa = PBXBuildFile; fileRef = 242F776C1C730DCF005EFFA4 /* AMAppExportToIPA.xcscheme */; };
13 | 242F77701C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 242F776F1C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.m */; };
14 | 242F77731C730DCF005EFFA4 /* NSObject_Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 242F77721C730DCF005EFFA4 /* NSObject_Extension.m */; };
15 | 242F777C1C730E90005EFFA4 /* NSObject+MethodSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 242F777B1C730E90005EFFA4 /* NSObject+MethodSwizzler.m */; };
16 | 242F77801C730F37005EFFA4 /* NSObject+PopupMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 242F777F1C730F37005EFFA4 /* NSObject+PopupMenu.m */; };
17 | 244D1FC31C731BDA00AE7959 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 244D1FC11C731BDA00AE7959 /* LICENSE */; };
18 | 244D1FC41C731BDA00AE7959 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 244D1FC21C731BDA00AE7959 /* README.md */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | 242F77631C730DCF005EFFA4 /* AMAppExportToIPA.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMAppExportToIPA.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; };
23 | 242F77661C730DCF005EFFA4 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
24 | 242F77681C730DCF005EFFA4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
25 | 242F776C1C730DCF005EFFA4 /* AMAppExportToIPA.xcscheme */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = AMAppExportToIPA.xcscheme; path = AMAppExportToIPA.xcodeproj/xcshareddata/xcschemes/AMAppExportToIPA.xcscheme; sourceTree = SOURCE_ROOT; };
26 | 242F776E1C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AMAppExportToIPAXcodePlugin.h; sourceTree = ""; };
27 | 242F776F1C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AMAppExportToIPAXcodePlugin.m; sourceTree = ""; };
28 | 242F77711C730DCF005EFFA4 /* NSObject_Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSObject_Extension.h; sourceTree = ""; };
29 | 242F77721C730DCF005EFFA4 /* NSObject_Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSObject_Extension.m; sourceTree = ""; };
30 | 242F77741C730DCF005EFFA4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | 242F777A1C730E90005EFFA4 /* NSObject+MethodSwizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MethodSwizzler.h"; sourceTree = ""; };
32 | 242F777B1C730E90005EFFA4 /* NSObject+MethodSwizzler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MethodSwizzler.m"; sourceTree = ""; };
33 | 242F777D1C730EF4005EFFA4 /* RuntimeHeaders.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RuntimeHeaders.h; sourceTree = ""; };
34 | 242F777E1C730F37005EFFA4 /* NSObject+PopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PopupMenu.h"; sourceTree = ""; };
35 | 242F777F1C730F37005EFFA4 /* NSObject+PopupMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PopupMenu.m"; sourceTree = ""; };
36 | 244D1FC11C731BDA00AE7959 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; };
37 | 244D1FC21C731BDA00AE7959 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
38 | /* End PBXFileReference section */
39 |
40 | /* Begin PBXFrameworksBuildPhase section */
41 | 242F77611C730DCF005EFFA4 /* Frameworks */ = {
42 | isa = PBXFrameworksBuildPhase;
43 | buildActionMask = 2147483647;
44 | files = (
45 | 242F77671C730DCF005EFFA4 /* AppKit.framework in Frameworks */,
46 | 242F77691C730DCF005EFFA4 /* Foundation.framework in Frameworks */,
47 | );
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | /* End PBXFrameworksBuildPhase section */
51 |
52 | /* Begin PBXGroup section */
53 | 242F775A1C730DCF005EFFA4 = {
54 | isa = PBXGroup;
55 | children = (
56 | 244D1FC11C731BDA00AE7959 /* LICENSE */,
57 | 244D1FC21C731BDA00AE7959 /* README.md */,
58 | 242F776A1C730DCF005EFFA4 /* AMAppExportToIPA */,
59 | 242F77651C730DCF005EFFA4 /* Frameworks */,
60 | 242F77641C730DCF005EFFA4 /* Products */,
61 | );
62 | sourceTree = "";
63 | };
64 | 242F77641C730DCF005EFFA4 /* Products */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 242F77631C730DCF005EFFA4 /* AMAppExportToIPA.xcplugin */,
68 | );
69 | name = Products;
70 | sourceTree = "";
71 | };
72 | 242F77651C730DCF005EFFA4 /* Frameworks */ = {
73 | isa = PBXGroup;
74 | children = (
75 | 242F77661C730DCF005EFFA4 /* AppKit.framework */,
76 | 242F77681C730DCF005EFFA4 /* Foundation.framework */,
77 | );
78 | name = Frameworks;
79 | sourceTree = "";
80 | };
81 | 242F776A1C730DCF005EFFA4 /* AMAppExportToIPA */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 242F776E1C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.h */,
85 | 242F776F1C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.m */,
86 | 242F77711C730DCF005EFFA4 /* NSObject_Extension.h */,
87 | 242F77721C730DCF005EFFA4 /* NSObject_Extension.m */,
88 | 242F777A1C730E90005EFFA4 /* NSObject+MethodSwizzler.h */,
89 | 242F777B1C730E90005EFFA4 /* NSObject+MethodSwizzler.m */,
90 | 242F777E1C730F37005EFFA4 /* NSObject+PopupMenu.h */,
91 | 242F777F1C730F37005EFFA4 /* NSObject+PopupMenu.m */,
92 | 242F777D1C730EF4005EFFA4 /* RuntimeHeaders.h */,
93 | 242F77741C730DCF005EFFA4 /* Info.plist */,
94 | 242F776B1C730DCF005EFFA4 /* Supporting Files */,
95 | );
96 | path = AMAppExportToIPA;
97 | sourceTree = "";
98 | };
99 | 242F776B1C730DCF005EFFA4 /* Supporting Files */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 242F776C1C730DCF005EFFA4 /* AMAppExportToIPA.xcscheme */,
103 | );
104 | name = "Supporting Files";
105 | sourceTree = "";
106 | };
107 | /* End PBXGroup section */
108 |
109 | /* Begin PBXNativeTarget section */
110 | 242F77621C730DCF005EFFA4 /* AMAppExportToIPA */ = {
111 | isa = PBXNativeTarget;
112 | buildConfigurationList = 242F77771C730DCF005EFFA4 /* Build configuration list for PBXNativeTarget "AMAppExportToIPA" */;
113 | buildPhases = (
114 | 242F775F1C730DCF005EFFA4 /* Sources */,
115 | 242F77601C730DCF005EFFA4 /* Resources */,
116 | 242F77611C730DCF005EFFA4 /* Frameworks */,
117 | );
118 | buildRules = (
119 | );
120 | dependencies = (
121 | );
122 | name = AMAppExportToIPA;
123 | productName = AMAppExportToIPA;
124 | productReference = 242F77631C730DCF005EFFA4 /* AMAppExportToIPA.xcplugin */;
125 | productType = "com.apple.product-type.bundle";
126 | };
127 | /* End PBXNativeTarget section */
128 |
129 | /* Begin PBXProject section */
130 | 242F775B1C730DCF005EFFA4 /* Project object */ = {
131 | isa = PBXProject;
132 | attributes = {
133 | LastUpgradeCheck = 0720;
134 | ORGANIZATIONNAME = Tendencystudio;
135 | TargetAttributes = {
136 | 242F77621C730DCF005EFFA4 = {
137 | CreatedOnToolsVersion = 7.2.1;
138 | };
139 | };
140 | };
141 | buildConfigurationList = 242F775E1C730DCF005EFFA4 /* Build configuration list for PBXProject "AMAppExportToIPA" */;
142 | compatibilityVersion = "Xcode 3.2";
143 | developmentRegion = English;
144 | hasScannedForEncodings = 0;
145 | knownRegions = (
146 | en,
147 | );
148 | mainGroup = 242F775A1C730DCF005EFFA4;
149 | productRefGroup = 242F77641C730DCF005EFFA4 /* Products */;
150 | projectDirPath = "";
151 | projectRoot = "";
152 | targets = (
153 | 242F77621C730DCF005EFFA4 /* AMAppExportToIPA */,
154 | );
155 | };
156 | /* End PBXProject section */
157 |
158 | /* Begin PBXResourcesBuildPhase section */
159 | 242F77601C730DCF005EFFA4 /* Resources */ = {
160 | isa = PBXResourcesBuildPhase;
161 | buildActionMask = 2147483647;
162 | files = (
163 | 244D1FC31C731BDA00AE7959 /* LICENSE in Resources */,
164 | 242F776D1C730DCF005EFFA4 /* AMAppExportToIPA.xcscheme in Resources */,
165 | );
166 | runOnlyForDeploymentPostprocessing = 0;
167 | };
168 | /* End PBXResourcesBuildPhase section */
169 |
170 | /* Begin PBXSourcesBuildPhase section */
171 | 242F775F1C730DCF005EFFA4 /* Sources */ = {
172 | isa = PBXSourcesBuildPhase;
173 | buildActionMask = 2147483647;
174 | files = (
175 | 242F77701C730DCF005EFFA4 /* AMAppExportToIPAXcodePlugin.m in Sources */,
176 | 242F777C1C730E90005EFFA4 /* NSObject+MethodSwizzler.m in Sources */,
177 | 244D1FC41C731BDA00AE7959 /* README.md in Sources */,
178 | 242F77731C730DCF005EFFA4 /* NSObject_Extension.m in Sources */,
179 | 242F77801C730F37005EFFA4 /* NSObject+PopupMenu.m in Sources */,
180 | );
181 | runOnlyForDeploymentPostprocessing = 0;
182 | };
183 | /* End PBXSourcesBuildPhase section */
184 |
185 | /* Begin XCBuildConfiguration section */
186 | 242F77751C730DCF005EFFA4 /* Debug */ = {
187 | isa = XCBuildConfiguration;
188 | buildSettings = {
189 | ALWAYS_SEARCH_USER_PATHS = NO;
190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
191 | CLANG_CXX_LIBRARY = "libc++";
192 | CLANG_ENABLE_MODULES = YES;
193 | CLANG_ENABLE_OBJC_ARC = YES;
194 | CLANG_WARN_BOOL_CONVERSION = YES;
195 | CLANG_WARN_CONSTANT_CONVERSION = YES;
196 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
197 | CLANG_WARN_EMPTY_BODY = YES;
198 | CLANG_WARN_ENUM_CONVERSION = YES;
199 | CLANG_WARN_INT_CONVERSION = YES;
200 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
201 | CLANG_WARN_UNREACHABLE_CODE = YES;
202 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
203 | COPY_PHASE_STRIP = NO;
204 | DEBUG_INFORMATION_FORMAT = dwarf;
205 | ENABLE_STRICT_OBJC_MSGSEND = YES;
206 | ENABLE_TESTABILITY = YES;
207 | GCC_C_LANGUAGE_STANDARD = gnu99;
208 | GCC_DYNAMIC_NO_PIC = NO;
209 | GCC_NO_COMMON_BLOCKS = YES;
210 | GCC_OPTIMIZATION_LEVEL = 0;
211 | GCC_PREPROCESSOR_DEFINITIONS = (
212 | "DEBUG=1",
213 | "$(inherited)",
214 | );
215 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
216 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
217 | GCC_WARN_UNDECLARED_SELECTOR = YES;
218 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
219 | GCC_WARN_UNUSED_FUNCTION = YES;
220 | GCC_WARN_UNUSED_VARIABLE = YES;
221 | MTL_ENABLE_DEBUG_INFO = YES;
222 | ONLY_ACTIVE_ARCH = YES;
223 | };
224 | name = Debug;
225 | };
226 | 242F77761C730DCF005EFFA4 /* Release */ = {
227 | isa = XCBuildConfiguration;
228 | buildSettings = {
229 | ALWAYS_SEARCH_USER_PATHS = NO;
230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
231 | CLANG_CXX_LIBRARY = "libc++";
232 | CLANG_ENABLE_MODULES = YES;
233 | CLANG_ENABLE_OBJC_ARC = YES;
234 | CLANG_WARN_BOOL_CONVERSION = YES;
235 | CLANG_WARN_CONSTANT_CONVERSION = YES;
236 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
237 | CLANG_WARN_EMPTY_BODY = YES;
238 | CLANG_WARN_ENUM_CONVERSION = YES;
239 | CLANG_WARN_INT_CONVERSION = YES;
240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
241 | CLANG_WARN_UNREACHABLE_CODE = YES;
242 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
243 | COPY_PHASE_STRIP = NO;
244 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
245 | ENABLE_NS_ASSERTIONS = NO;
246 | ENABLE_STRICT_OBJC_MSGSEND = YES;
247 | GCC_C_LANGUAGE_STANDARD = gnu99;
248 | GCC_NO_COMMON_BLOCKS = YES;
249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
250 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
251 | GCC_WARN_UNDECLARED_SELECTOR = YES;
252 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
253 | GCC_WARN_UNUSED_FUNCTION = YES;
254 | GCC_WARN_UNUSED_VARIABLE = YES;
255 | MTL_ENABLE_DEBUG_INFO = NO;
256 | };
257 | name = Release;
258 | };
259 | 242F77781C730DCF005EFFA4 /* Debug */ = {
260 | isa = XCBuildConfiguration;
261 | buildSettings = {
262 | COMBINE_HIDPI_IMAGES = YES;
263 | DEPLOYMENT_LOCATION = YES;
264 | DSTROOT = "$(HOME)";
265 | INFOPLIST_FILE = AMAppExportToIPA/Info.plist;
266 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
267 | MACOSX_DEPLOYMENT_TARGET = 10.10;
268 | PRODUCT_BUNDLE_IDENTIFIER = com.tendencystudio.AMAppExportToIPA;
269 | PRODUCT_NAME = "$(TARGET_NAME)";
270 | WRAPPER_EXTENSION = xcplugin;
271 | };
272 | name = Debug;
273 | };
274 | 242F77791C730DCF005EFFA4 /* Release */ = {
275 | isa = XCBuildConfiguration;
276 | buildSettings = {
277 | COMBINE_HIDPI_IMAGES = YES;
278 | DEPLOYMENT_LOCATION = YES;
279 | DSTROOT = "$(HOME)";
280 | INFOPLIST_FILE = AMAppExportToIPA/Info.plist;
281 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
282 | MACOSX_DEPLOYMENT_TARGET = 10.10;
283 | PRODUCT_BUNDLE_IDENTIFIER = com.tendencystudio.AMAppExportToIPA;
284 | PRODUCT_NAME = "$(TARGET_NAME)";
285 | WRAPPER_EXTENSION = xcplugin;
286 | };
287 | name = Release;
288 | };
289 | /* End XCBuildConfiguration section */
290 |
291 | /* Begin XCConfigurationList section */
292 | 242F775E1C730DCF005EFFA4 /* Build configuration list for PBXProject "AMAppExportToIPA" */ = {
293 | isa = XCConfigurationList;
294 | buildConfigurations = (
295 | 242F77751C730DCF005EFFA4 /* Debug */,
296 | 242F77761C730DCF005EFFA4 /* Release */,
297 | );
298 | defaultConfigurationIsVisible = 0;
299 | defaultConfigurationName = Release;
300 | };
301 | 242F77771C730DCF005EFFA4 /* Build configuration list for PBXNativeTarget "AMAppExportToIPA" */ = {
302 | isa = XCConfigurationList;
303 | buildConfigurations = (
304 | 242F77781C730DCF005EFFA4 /* Debug */,
305 | 242F77791C730DCF005EFFA4 /* Release */,
306 | );
307 | defaultConfigurationIsVisible = 0;
308 | defaultConfigurationName = Release;
309 | };
310 | /* End XCConfigurationList section */
311 | };
312 | rootObject = 242F775B1C730DCF005EFFA4 /* Project object */;
313 | }
314 |
--------------------------------------------------------------------------------