Search code examples
objective-ccoding-styleobjective-c-category

Objective-C Coding Style - Categories instead of Marks?


Is there a downside to dividing implementation of Objective-C classes into categories, for code organization reasons. Instead of using the conventional #pragma mark - SectionTitle way?

Below I've included contrasting samples of a portion of a single implementation file.

Category Approach

@implementation Gallery

+ (NSArray*)titles
{
  return @[@"St. Augustine", @"Roanoke", @"Jamestown", @"Santa Fe"];
}

@end

@implementation Gallery (Overrides)

- (NSString*)description
{
  return self.title;
}

- (NSString*)debugDescription
{
  return [NSString stringWithFormat:@"%@ - %u items",
          self.title, (unsigned int)[self.items count]];
}

@end

@implementation Gallery (Debug)

+ (instancetype) randomGalleryWithTitle:(NSString*)title;
{
  Gallery *gallery = [[Gallery alloc] init];

  gallery.title = title;
  gallery.iconImageName = title;

  NSMutableArray *items = [NSMutableArray array];
  for (int i = 0; i < 20; ++i) {

    if(rand() % 2 == 0) {
      ArtObject *randomArtObject = [ArtObject randomArtObject];
      randomArtObject.galleryTitle = gallery.title;
      [items addObject:randomArtObject];
    } else {
      Story *randomStory = [Story randomStory];
      randomStory.galleryTitle = gallery.title;
      [items addObject:randomStory];
    }
  }

  gallery.items = items;

  return gallery;
}

@end

Conventional Approach

@implementation Gallery

+ (NSArray*)titles
{
  return @[@"St. Augustine", @"Roanoke", @"Jamestown", @"Santa Fe"];
}

@end

#pragma mark - Overrides

- (NSString*)description
{
  return self.title;
}

- (NSString*)debugDescription
{
  return [NSString stringWithFormat:@"%@ - %u items",
          self.title, (unsigned int)[self.items count]];
}

@end

#pragma mark - Debug

+ (instancetype) randomGalleryWithTitle:(NSString*)title;
{
  Gallery *gallery = [[Gallery alloc] init];

  gallery.title = title;
  gallery.iconImageName = title;

  NSMutableArray *items = [NSMutableArray array];
  for (int i = 0; i < 20; ++i) {

    if(rand() % 2 == 0) {
      ArtObject *randomArtObject = [ArtObject randomArtObject];
      randomArtObject.galleryTitle = gallery.title;
      [items addObject:randomArtObject];
    } else {
      Story *randomStory = [Story randomStory];
      randomStory.galleryTitle = gallery.title;
      [items addObject:randomStory];
    }
  }

  gallery.items = items;

  return gallery;
}

@end

Solution

  • From "Customizing Existing Classes" in the "Programming with Objective-C" guide:

    At runtime, there’s no difference between a method added by a category and one that is implemented by the original class.

    So you can choose whatever you find more intuitive for managing your code. There will be no difference at runtime.