Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Desenvolvendo um plugin para o Xcode

Marcelo
March 01, 2016

Desenvolvendo um plugin para o Xcode

Palestra apresentada no 19º CocoaHeads São Paulo (01/03/2016).

Como você deve saber, o Xcode não é exatamente mil maravilhas. Entretanto, existe uma forma de adicionar ou alterar funcionalidades: plugins. Será mostrado as motivações para se criar um plugin, assim como os passos necessários.

Marcelo

March 01, 2016
Tweet

More Decks by Marcelo

Other Decks in Technology

Transcript

  1. BOILERPLATE @implementation IBOutlint + (instancetype)sharedPlugin { return sharedPlugin; } -

    (id)initWithBundle:(NSBundle *)plugin { if (self = [super init]) { // reference to plugin's bundle, for resource access self.bundle = plugin; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didApplicationFinishLaunchingNotification:) name:NSApplicationDidFinishLaunchingNotification object:nil]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
  2. - (void)didApplicationFinishLaunchingNotification:(NSNotification*)noti { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center removeObserver:self

    name:NSApplicationDidFinishLaunchingNotification object:nil]; [center addObserver:self selector:@selector(editorDocumentChanged:) name:@"IDEEditorDocumentDidChangeNotification" object:nil]; }
  3. - (void)editorDocumentChanged:(NSNotification *)notification { NSArray *array = notification.userInfo[@"IDEEditorDocumentChangeLocationsKey"]; id firstChange

    = array.firstObject; NSURL *url = [firstChange valueForKey:@"documentURL"]; if ([url isKindOfClass:[NSNull class]]) { return; } NSRange range = [[firstChange valueForKey:@"characterRange"] rangeValue]; // Check if it's a valid range if (range.length == 0 || range.location == NSNotFound) { return; }
  4. // Check if it's an IDESourceCodeDocument if (![notification.object respondsToSelector:@selector(textStorage)]) {

    return; } id textStorage = [notification.object textStorage]; NSAttributedString *attributed; @try { attributed = [textStorage attributedSubstringFromRange:range]; } @catch (NSException *exception) { return; }
  5. NSString *substring = attributed.string; NSDictionary *mapping = @{ @"@property (weak,

    nonatomic) IBOutlet " : @"@property (nonatomic, weak) IBOutlet ", @"@property (strong, nonatomic) IBOutlet " : @"@property (nonatomic, strong) IBOutlet " };
  6. [mapping enumerateKeysAndObjectsUsingBlock:^(NSString *prefix, NSString *replacement, BOOL * _Nonnull stop) {

    if ([substring hasPrefix:prefix]) { NSString *updatedSubstring = [substring stringByReplacingOccurrencesOfString:prefix withString:replacement]; [textStorage beginEditing]; [textStorage replaceCharactersInRange:range withString:updatedSubstring withUndoManager:nil]; [textStorage endEditing]; } }];
  7. INCLUINDO NO ALCATRAZ { "name": "IBOutlint", "url": "https://github.com/marcelofabri/IBOutlint", "description": "Xcode

    plugin to change the order of the attributes when creating an IBOutlet in Xcode", "screenshot": "https://raw.githubusercontent.com/marcelofabri/IBOutlint/master/IBOutlint.gif" }
  8. !

  9. CONSELHOS > Sempre que puder, evite method swizzling > Muitos

    plugins são open source, dê uma olhada neles > Xcode-RuntimeHeaders > Se algum plugin não funcionar, pode ser por causa do UUID do Xcode