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

Desenvolvendo um plugin para o Xcode

Avatar for Marcelo 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.

Avatar for Marcelo

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