Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old May 6, 2013, 06:37 PM   #1
ArtOfWarfare
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Writing Plugins for Xcode 4

Hi guys,

I'm not asking for help with this (yet) but I thought I'd just share this article with anyone who might be interested in doing anything similar:

http://blacksmithsoftware.com/blog/2...xcode4-plugins
__________________
Battery Status - On the Mac App Store
The only app that'll estimate when your wireless devices will need their batteries changed.
Including the ones paired with other Macs on your network.
ArtOfWarfare is offline   0 Reply With Quote
Old May 6, 2013, 09:11 PM   #2
PatrickCocoa
macrumors 6502a
 
Join Date: Dec 2008
Looks cool

Looks cool. Once you get started, can you extend KSImageNamed to show (in addition to the autocompleted list of names of .jpg and .png) the image size?
__________________
iMac 21.5", 3.06GHz, 4 GB, 2 TB HD.
iPod Touch 3G.
PatrickCocoa is offline   0 Reply With Quote
Old May 6, 2013, 09:29 PM   #3
ArtOfWarfare
Thread Starter
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
Quote:
Originally Posted by PatrickCocoa View Post
Looks cool. Once you get started, can you extend KSImageNamed to show (in addition to the autocompleted list of names of .jpg and .png) the image size?
I'm not sure what you're talking about, but based on what I've seen so far for Xcode 4 Plugins, I'd imagine so.
ArtOfWarfare is offline   0 Reply With Quote
Old May 7, 2013, 03:16 PM   #4
ArtOfWarfare
Thread Starter
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
These were a helpful few lines to expedite debugging (add in a new Build Phrase -> Run Script at the end of your Build Phases for your target):

Code:
killall -9 Xcode
sleep 0.3
rm -fR ~/Library/Developer/Xcode/DerivedData
open /Applications/Utilities/Console.app
open /Applications/Xcode.app
This will restart Xcode so it will load the plugin as soon as it has finished building it and it'll also bring up Console so that you can view any NSLog statements you're using to debug.

Alternatively, you could do:

Code:
open -n /Applications/Xcode.app
Which will launch a second instance of Xcode which will have your new plugin while leaving the original instance alone. I didn't experiment with this much because my computer only has 2 GB of RAM so was going really slowly with two instances of Xcode running.

If you wanted to pursue that route, you should possibly do something involving the command GDB so that debugging features besides NSLog would work... I didn't get that far because I just don't have the memory to throw around experimenting with that.

Edit: I have found that running this code after Xcode finishes initializing is helpful with figuring out how to address different UIElements:

Code:
	NSArray *allWindows = [NSApp windows];
	[allWindows enumerateObjectsUsingBlock:^(NSWindow *window, NSUInteger idx, BOOL *stop) {
		if (window.isVisible) {
			[self recursivlyPrintSubviews:window.contentView
							  superOrigin:window.frame.origin
								  padding:[NSString stringWithFormat:@"%ld-", (unsigned long)idx]];
		} else {
			NSLog(@"%ld-Hidden Window", (unsigned long)idx);
		}
	}];
Code:
- (void)recursivlyPrintSubviews:(NSView *)view superOrigin:(CGPoint)superOrigin padding:(NSString *)pad
{
	if (!NSEqualRects(view.visibleRect, NSZeroRect)) {
		NSString *string = @"";
		if ([view respondsToSelector:@selector(title)]) {
			string = [view title];
		} else if ([view respondsToSelector:@selector(stringValue)]) {
			string = [view stringValue];
		}
		CGFloat originX = superOrigin.x + view.frame.origin.x;
		CGFloat originY = superOrigin.y + view.frame.origin.y;
		NSLog(@"%@%@: \"%@\" %@", pad, [view class], string, NSStringFromRect(CGRectMake(originX, originY, view.frame.size.width, view.frame.size.height)));
		NSArray *allSubviews = view.subviews;
		[allSubviews enumerateObjectsUsingBlock:^(NSView *subview, NSUInteger idx, BOOL *stop) {
			[self recursivlyPrintSubviews:subview
							  superOrigin:CGPointMake(originX, originY)
								  padding:[NSString stringWithFormat:@"%@%ld-", pad, (unsigned long)idx]];
		}];
	} else {
		NSLog(@"%@Fully Obscured View", pad);
	}
}
In my case, this yielded the following output, which let me know that the sidebar visible on the left hand side of the main Xcode window is of the class IDENavigatorOutlineView - presumably a subclass of NSOutlineView, which means I can look into the methods that class provides to get an idea of how I can interact with Apple's private subclass (I'm finding this to be one of the most exciting programming projects I've ever worked on...)

Code:
0-Hidden Window
1-NSView: "" {{0, 352}, {1280, 352}}
1-0-DVTTabSwitcher: "" {{0, 352}, {1280, 350}}
1-0-0-NSTabView: "" {{0, 352}, {1280, 350}}
1-0-0-0-DVTControllerContentView: "" {{0, 352}, {1280, 350}}
1-0-0-0-0-DVTSplitView: "" {{0, 352}, {1280, 350}}
1-0-0-0-0-0-DVTReplacementView: "" {{0, 352}, {260, 350}}
1-0-0-0-0-0-0-DVTControllerContentView: "" {{0, 352}, {260, 350}}
1-0-0-0-0-0-0-0-NSView: "" {{0, 352}, {260, 350}}
1-0-0-0-0-0-0-0-0-DVTBorderedView: "" {{0, 374}, {260, 306}}
1-0-0-0-0-0-0-0-0-0-DVTReplacementView: "" {{0, 374}, {259, 306}}
1-0-0-0-0-0-0-0-0-0-0-DVTControllerContentView: "" {{0, 374}, {259, 306}}
1-0-0-0-0-0-0-0-0-0-0-0-NSScrollView: "" {{0, 374}, {259, 306}}
1-0-0-0-0-0-0-0-0-0-0-0-0-NSClipView: "" {{0, 374}, {259, 306}}
1-0-0-0-0-0-0-0-0-0-0-0-0-0-IDENavigatorOutlineView: "" {{0, 374}, {259, 306}}
1-0-0-0-0-0-0-0-0-0-0-0-1--Fully Obscured View
1-0-0-0-0-0-0-0-0-0-0-0-2--Fully Obscured View
1-0-0-0-0-0-0-0-1-DVTChooserView: "" {{0, 680}, {260, 22}}
1-0-0-0-0-0-0-0-1-0-NSMatrix: "1" {{18, 681}, {225, 21}}
1-0-0-0-0-0-0-0-2-DVTBorderedView: "" {{0, 352}, {260, 22}}
1-0-0-0-0-0-0-0-2-0-IDENavigatorFilterControlBar: "" {{0, 352}, {259, 22}}
1-0-0-0-0-0-0-0-2-0-0-DVTSearchField: "" {{89, 353}, {164, 19}}
1-0-0-0-0-0-0-0-2-0-1-DVTRolloverImageButton: "Button" {{30, 353}, {17, 21}}
1-0-0-0-0-0-0-0-2-0-2-DVTRolloverImageButton: "Button" {{49, 353}, {17, 21}}
1-0-0-0-0-0-0-0-2-0-3-DVTRolloverImageButton: "Button" {{68, 353}, {17, 21}}
1-0-0-0-0-0-0-0-2-0-4-IDEFilterBarGradientImagePopUpButton: "" {{0, 352}, {25, 21}}
1-0-0-0-0-1-DVTReplacementView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-DVTControllerContentView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-DVTSplitView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-0-DVTLayoutView_ML: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-0-0--Fully Obscured View
1-0-0-0-0-1-0-0-0-1-NSView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-0-1-0-DVTControllerContentView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-0-1-0-0-DVTControllerContentView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-0-1-0-0-0-NSView: "" {{260, 352}, {760, 350}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-IDENavBar: "" {{260, 680}, {760, 22}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-0-DVTBorderedView: "" {{341, 680}, {631, 22}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-0-0-IDEPathControl: "" {{341, 681}, {631, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-IDEControlGroup: "" {{260, 680}, {81, 22}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-0-DVTBorderedView: "" {{260, 681}, {28, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-0-0-DVTGradientImagePopUpButton: "" {{260, 681}, {28, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-1-DVTBorderedView: "" {{288, 681}, {27, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-1-0-DVTDelayedMenuGradientImageButton: "" {{288, 681}, {27, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-2-DVTBorderedView: "" {{315, 681}, {26, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-1-2-0-DVTDelayedMenuGradientImageButton: "" {{315, 681}, {26, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-2-IDEControlGroup: "" {{972, 680}, {48, 22}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-2-0-DVTBorderedView: "" {{973, 681}, {47, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-2-0-0-IDEEditorMenuStepperView: "" {{973, 681}, {47, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-2-0-0-0-_IDEEditorStepperArrowButton: "" {{973, 681}, {15, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-2-0-0-1-_IDEEditorStepperArrowButton: "" {{1005, 681}, {15, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-0-2-0-0-2-IDEActionButton: "" {{988, 681}, {17, 21}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-DVTBorderedView: "" {{260, 352}, {760, 328}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-DVTControllerContentView: "" {{260, 352}, {760, 328}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-IDESourceCodeEditorContainerView: "" {{260, 352}, {760, 328}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-0-DVTSourceTextScrollView: "" {{260, 352}, {760, 328}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-0-0-NSClipView: "" {{295, 352}, {725, 328}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-0-0-0-DVTSourceTextView: "" {{295, 352}, {1104, 1513}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-0-1-NSScroller: "" {{295, 665}, {719, 15}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-0-2-DVTMarkedScroller: "" {{1005, 352}, {15, 322}}
1-0-0-0-0-1-0-0-0-1-0-0-0-1-0-0-0-3-DVTTextSidebarView: "" {{260, 352}, {35, 328}}
1-0-0-0-0-1-0-0-0-1-0-0-0-2--Fully Obscured View
1-0-0-0-0-1-0-0-1--Fully Obscured View
1-0-0-0-0-2-DVTSplitView: "" {{1020, 352}, {260, 350}}
1-0-0-0-0-2-0-DVTReplacementView: "" {{1020, 352}, {260, 328}}
1-0-0-0-0-2-0-0-DVTControllerContentView: "" {{1020, 352}, {260, 328}}
1-0-0-0-0-2-0-0-0-NSView: "" {{1020, 352}, {260, 328}}
1-0-0-0-0-2-0-0-0-0-DVTChooserView: "" {{1020, 658}, {260, 22}}
1-0-0-0-0-2-0-0-0-0-0-NSMatrix: "1" {{1118, 659}, {65, 21}}
1-0-0-0-0-2-0-0-0-1-DVTBorderedView: "" {{1020, 352}, {260, 306}}
1-0-0-0-0-2-0-0-0-1-0-NSScrollView: "" {{1021, 352}, {259, 306}}
1-0-0-0-0-2-0-0-0-1-0-0-NSClipView: "" {{1021, 352}, {259, 306}}
1-0-0-0-0-2-0-0-0-1-0-0-0-DVTStackView_ML: "" {{1021, 352}, {259, 100}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-DVTDisclosureView: "" {{1021, 352}, {259, 100}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-0-DVTDisclosureHeaderView: "Quick Help" {{1021, 352}, {259, 19}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-0-0-NSButton: "Button" {{1024, 355}, {13, 13}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-0-1-NSTextField: "Quick Help" {{1040, 355}, {237, 13}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-0-2--Fully Obscured View
1-0-0-0-0-2-0-0-0-1-0-0-0-0-0-3--Fully Obscured View
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-DVTControllerContentView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-WebView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-0-WebFrameView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-0-0-WebDynamicScrollBarsView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-0-0-0-WebClipView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-0-0-0-0-WebHTMLView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-0-0-1--Fully Obscured View
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-1-IDEQuickHelpPlaceholderView: "" {{1021, 371}, {259, 80}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-1-0-DVTLozengeTextField: "No Quick Help" {{1088, 399}, {124, 39}}
1-0-0-0-0-2-0-0-0-1-0-0-0-0-1-0-1-1-NSButton: "Search Documentation" {{1083, 383}, {135, 17}}
1-0-0-0-0-2-0-0-0-1-0-1--Fully Obscured View
1-0-0-0-0-2-0-0-0-1-0-2--Fully Obscured View
1-0-0-0-0-2-1-DVTReplacementView: "" {{1020, 680}, {260, 22}}
1-0-0-0-0-2-1-0-DVTControllerContentView: "" {{1020, 680}, {260, 22}}
1-0-0-0-0-2-1-0-0-NSView: "" {{1020, 491}, {260, 211}}
1-0-0-0-0-2-1-0-0-0-DVTChooserView: "" {{1020, 679}, {260, 23}}
1-0-0-0-0-2-1-0-0-0-0-NSMatrix: "1" {{1086, 680}, {129, 21}}
1-0-0-0-0-2-1-0-0-1--Fully Obscured View
1-1-DVTTabBarEnclosureView: "" {{0, 702}, {1280, 2}}
1-1-0--Fully Obscured View
2-Hidden Window
(Previously I had it printing out all views, but there was such a huge list of them that - though it was surprising they existed even though I was a few clicks away from being able to see them - weren't helpful.)

Edit 2X: I wrote a plugin that lets me browser MacRumors whenever I click on a framework on the navigation bar in Xcode... although I can manage posts, it seems that I can't upload attachments from this... I'll have to switch to Safari to upload a screenshot of it. In the screenshot you can see that the navigation bar above the editor doesn't change properly... further, the navigation bar doesn't allow you to select frameworks using it. Also, my code doesn't properly account for the possibility of multiple tabs, windows, or assistants right now, but still, I'm getting excited about the possibilities here...
Attached Thumbnails
Click image for larger version

Name:	Xcode-WebView.png
Views:	24
Size:	279.8 KB
ID:	411542  

Last edited by ArtOfWarfare; May 11, 2013 at 01:16 AM.
ArtOfWarfare is offline   0 Reply With Quote
Old May 11, 2013, 01:31 AM   #5
ArtOfWarfare
Thread Starter
macrumors 603
 
ArtOfWarfare's Avatar
 
Join Date: Nov 2007
Send a message via Skype™ to ArtOfWarfare
I feel like tearing apart Xcode like this is teaching me a lot about the structure of OS X apps and GUIs...

Anyways, my prior print method wasn't actually telling me everything there was to know about the view hierarchy, because I was leaving off the toolbar. Toolbars belong directly to windows, and the items within them have labels. So I added this code in my window enumerator to print off a list of the toolbars:

Code:
NSLog(@"%ld-Toolbar Contains:", (unsigned long) idx);
[[window.toolbar visibleItems] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSLog(@"   %@", [obj label]);
}];
This yielded:
Code:
Run
Stop
Scheme
Breakpoints

Editor
View
Organizer
Where the gap is an unlabeled toolbar item of the subclass _IDEActivityViewControllerToolbarItem

The fun really hasn't let up here in the week since I first started looking into making a plugin for Xcode... although I should knock it off with this project since there's other more important (IE, paid) work I should be doing...
__________________
Battery Status - On the Mac App Store
The only app that'll estimate when your wireless devices will need their batteries changed.
Including the ones paired with other Macs on your network.
ArtOfWarfare is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
The best plugins? InfiniteLoopy Digital Photography 22 May 31, 2014 09:18 PM
Moving from xcode 3.2 to xcode 4.5.2 compilation error for 'abs' macro in stdlib.h hrishidev Mac Programming 7 Jun 2, 2013 10:36 AM
Xcode 3 vs Xcode 4 when dealing with Objective-C timebourne Mac Programming 8 Sep 23, 2012 05:36 PM
XCode 4.4.1 to Xcode 4.5 in Mountain Lion VinegarTasters OS X 10.8 Mountain Lion 2 Sep 19, 2012 08:55 PM
DSP Plugins -dms- PowerPC Macs 0 Jul 12, 2012 10:56 AM

Forum Jump

All times are GMT -5. The time now is 12:15 PM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC