Desenvolvendo um plugin para o Xcode

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.

841a0284060fa6faa652e95a467dcc69?s=128

Marcelo Fabri

March 01, 2016
Tweet

Transcript

  1. 2.
  2. 6.
  3. 8.
  4. 9.
  5. 10.
  6. 11.
  7. 13.

    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]; }
  8. 14.

    - (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]; }
  9. 15.

    - (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; }
  10. 16.

    // 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; }
  11. 17.

    NSString *substring = attributed.string; NSDictionary *mapping = @{ @"@property (weak,

    nonatomic) IBOutlet " : @"@property (nonatomic, weak) IBOutlet ", @"@property (strong, nonatomic) IBOutlet " : @"@property (nonatomic, strong) IBOutlet " };
  12. 18.

    [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]; } }];
  13. 20.
  14. 23.
  15. 25.

    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" }
  16. 26.

    !

  17. 27.

    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