在应用程序中跨类共享方法的最佳实践是什么?

时间:2012-03-12 19:56:57

标签: objective-c ios

我仍然试图围绕如何在面向对象的世界中完成事情,我认为我的问题是我不明白如何最好地利用封装。具体来说,我在项目的几个类中使用了很多小代码。例如:

+ (NSString *)getFormattedDate;
+ (NSString *)getResultsFilePath;
+ (NSError *)removeFileFromCache:(NSString *)fileName;

这些都是我在多个班级中使用的3-5行方法。我的标准做法是将这些片段放入Utility.inc文件中,并在需要时调用它们。这在面向对象的世界中是适当的还是每个类都应该是独立的?如果它是合适的,你会将代码放入一个单例或只是一个常规类文件和[[Utilities alloc] init]在你想要使用这些方法的每个类中吗?

3 个答案:

答案 0 :(得分:2)

使用Categories。对于您给出的示例,这些是与特定类的对象相关的方法,这些对象碰巧在您自己的几个类中使用。类别将允许您将这些常用的方法停放在可以与公共因子相关联的位置。

答案 1 :(得分:0)

创建一个实用程序单例,只创建一个,然后由其他类使用。

答案 2 :(得分:0)

感谢您的回答。我不确定这是做正确事情的正确方法,但这就是我对刚才提交的项目所做的。

我创建了两个类,一个用于Utility方法,另一个用于全局方法。 Utilities类中的方法都是类方法,因为它们对文件和常量或全局变量进行操作。然后我为全局变量做了一个单例。我在.pch文件中拥有所有全局常量。同样在.pch文件中,我添加了以下两行代码,以便实用程序和全局变量在任何地方都可用。

 // File for utilities like file delete, find Documents file
    #import "Utilities.h" 
    #import "Globals.h"

访问这些方法非常简单。以下是调用两种方法生成电子邮件HTML标头的示例。

NSString *gameNameHeader = [NSString stringWithFormat:@"<p>&nbsp</p><h1>%@ Results</h1><h2>%@%@</h2>",GAME_NAME_TITLE,[Utilities formattedClientName], [Utilities formattedDate]];

如果有人可以使用它,这是我当前版本的代码。 (对不起格式化 - 我似乎无法让wiki合作。)

@interface Utilities : NSObject {


}

+ (NSString *)formattedDate;
+ (NSString *)formattedClientName;

+ (NSString *)cachedResultsFilePath;
+ (NSString *)cachedResultsFileContents;
+ (NSString *)resultsFileName;
+ (NSError *)removeFileFromCache:(NSString *)fileName;

+ (NSString *)applicationCachesDirectory;
+ (NSString *)applicationDocumentsDirectory;
+ (NSString *)applicationLibraryDirectory;

+ (NSError *)copyCachedResultsToFile;
@end



    #import "Utilities.h"
@implementation Utilities {

    }

+ (NSString *)formattedDate {
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
    NSString *todaysDate = [dateFormatter stringFromDate:[NSDate date]];
    return todaysDate;
}

+ (NSString *)formattedClientName {
    NSString *client = [NSString stringWithFormat:@" "]; 
    if( [Globals sharedInstance].currentClient ) client = [NSString stringWithFormat:@" %@ ",[Globals sharedInstance].currentClient];
    return client;
}

+ (NSString *)cachedResultsFilePath {
    NSString *resultsFilePath = [[self applicationCachesDirectory] stringByAppendingPathComponent:@"Results.txt"];
    return resultsFilePath;
}

+ (NSString *)cachedResultsFileContents {
    NSStringEncoding encoding; NSError* error = nil;
    NSString *resultsText = [NSString stringWithContentsOfFile:[self cachedResultsFilePath] usedEncoding:&encoding error:&error];
    return resultsText;
}

+ (NSString *)resultsFileName {
    return [NSString stringWithFormat:@"%@ Results%@%@.html",GAME_NAME_TITLE,[self formattedClientName],[self formattedDate] ];

}

+ (NSError *)removeFileFromCache:(NSString *)fileName {
    NSError *error = nil;
    NSFileManager *localFileManager=[[NSFileManager alloc] init];
    NSString *fullPath = [NSString stringWithFormat:@"%@/%@", [self applicationCachesDirectory],fileName];
    [localFileManager removeItemAtPath: fullPath error:&error ];
    return error;
}

+ (NSString *)applicationCachesDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
}

+ (NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

+ (NSString *)applicationLibraryDirectory {

    return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
}

+ (NSError *)copyCachedResultsToFile {
    // Grab the header and footer and put it around the cached data
    NSStringEncoding encoding; NSError *error = nil;
    NSString *htmlHeaderTextPath = [[NSBundle mainBundle] pathForResource:@"HTML_header" ofType:@"html" ]; 
    NSString *htmlHeaderText = [NSString stringWithContentsOfFile:htmlHeaderTextPath usedEncoding:&encoding error:&error];

    NSString *cachedResultsText = [NSString stringWithContentsOfFile:[self cachedResultsFilePath] usedEncoding:&encoding error:&error];
    // Write the results to a file if there are any
    if (cachedResultsText) {
        NSString *htmlFooterTextPath = [[NSBundle mainBundle] pathForResource:@"HTML_footer" ofType:@"html" ]; 
        NSString *htmlFooterText = [NSString stringWithContentsOfFile:htmlFooterTextPath usedEncoding:&encoding error:&error];

        NSString *gameNameHeader = [NSString stringWithFormat:@"<h1>%@ Results for%@%@</h1>",GAME_NAME_TITLE,[self formattedClientName],[self formattedDate] ];
        NSString *tempStringP1 = [htmlHeaderText stringByAppendingString:gameNameHeader];
        NSString *tempStringP2 = [tempStringP1 stringByAppendingString:cachedResultsText];

        NSString *formattedTextForPrinting = [tempStringP2 stringByAppendingString:htmlFooterText];
        NSString *resultsFilePath = [ [Utilities applicationDocumentsDirectory] stringByAppendingPathComponent:[self resultsFileName] ];
        if ( !([[NSFileManager defaultManager] fileExistsAtPath:resultsFilePath]) ) {
            if (! ([[NSFileManager defaultManager] createFileAtPath:resultsFilePath contents:nil attributes:nil]) ) {
                NSLog(@"Error was code: %d - message: %s", errno, strerror(errno));
            }
        }
        NSFileHandle *fileHandler = [NSFileHandle fileHandleForUpdatingAtPath:resultsFilePath];
        [fileHandler writeData:[formattedTextForPrinting dataUsingEncoding:NSUTF8StringEncoding]];
        [fileHandler closeFile];

    }
     return error;
}
@end

单身人士中的全球人。可能不是线程安全的,但我现在不在乎。

@interface Globals : NSObject {


}
@property (nonatomic, strong) NSString *currentClient;
@property (nonatomic, strong) NSString *showmePict;
@property BOOL checkBoxes;

+ (Globals *)sharedInstance;

- (void)resetClient;

@end

@implementation Globals {

}

static Globals *singleton = nil;
@synthesize currentClient = _currentClient;
@synthesize showmePict = _showmePict;
@synthesize checkBoxes = _checkBoxes;

+(Globals *) sharedInstance {

    NSLog (@"sharedInstance of Globals called.");

    if (nil != singleton) return singleton;
    static dispatch_once_t pred;        // lock
    dispatch_once(&pred, ^{             // this code is at most once
        singleton = [[Globals alloc] init];
    });

    return singleton;

}

- (void)resetClient {
    self.currentClient = nil;
}


@end