Реализация вспомогательного фабричного метода на Objective-C

В широком смысле convenience метод - это вспомогательный метод созданный для того чтобы более сложная задача решалась более легко. Само название convenience означает удобство. Т.е. это метод созданный для того чтобы было удобно решать с его помощью более сложные задачи.

В примере ниже метод createWithString является convenience методом для создания экземпляров класса MyClass (в данном примере по сути это еще и фабричный метод).

//
//  MyClass.h
//

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@property (strong) NSString *myString;

- (id)init;
- (id)initWithString:(NSString *)aString;

+ (NSString *)transformString:(NSString *)aString;

+ (id)createWithString:(NSString *)aString;

@end


//
//  MyClass.m
//

#import "MyClass.h"

@implementation MyClass

- (id)init
{
    self = [super init];
    if (self) {
        // Do nothing
    }
    return self;
}

- (id)initWithString:(NSString *)aString
{
    self = [super init];
    if (self)
    {
         _myString = aString;
    }
    return self;
}

+ (NSString *)transformString:(NSString *)aString
{
    return [aString uppercaseString];
}

+ (id)createWithString:(NSString *)aString
{
#if !__has_feature(objc_arc)
    return [[[self alloc] initWithString:[self transformString:aString]] autorelease];
#else
    return [[self alloc] initWithString:[self transformString:aString]];
#endif
}

@end

Обратите внимание что self в статических методах указывает на класс, потому что в Objective-C всё является объектами, даже сами классы. Конечно здесь в статических методах вместо self можно было использовать имя класса MyClass, но это не дальновидно по той причине что наследники класса будут работать с классом своего предка, в то время как должны работать со своим собственным классом.

//
//  MySubclass.h
//

#import "MyClass.h"

@interface MySubclass : MyClass

@end



//
//  MySubclass.m
//

#import "MySubclass.h"

@implementation MySubclass

+ (NSString *)transformString:(NSString *)aString
{
    return [aString lowercaseString];
}

@end

MySubclass является наследником MyClass. Соответственно он наследует метод createWithString. Если бы мы в методе createWithString вместо self мы написали бы MyClass, то вызов этого метода у MySubclass возвращал бы объект типа MyClass.

То же касается и метода transformString, он вызывается у объекта self. Соответственно MyClass вызовет свою реализацию этого метода, а его наследник MySubclass свою (если она имеется).

//
//  main.m
//

#import <Foundation/Foundation.h>
#import "MyClass.h"
#import "MySubclass.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        MyClass *theMyObject1 = [MyClass createWithString:@"Hello, World!"];
        NSLog(@"%@", [theMyObject1 myString]);
        
        MySubclass *theMyObject2 = [MySubclass createWithString:@"Hello, World!"];
        NSLog(@"%@", [theMyObject2 myString]);
        
    }
    return 0;
}

Вывод программы:
2014-12-17 18:08:07.859 MyExample[3358:303] HELLO, WORLD!
2014-12-17 18:08:07.861 MyExample[3358:303] hello, world!
Program ended with exit code: 0

--