gpt4 book ai didi

ios - 与分析服务集成的架构/设计模式(flurry/google analytics)

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:00:54 25 4
gpt4 key购买 nike

我正在开发一个 iOS 应用程序,并计划在其中使用 分析 服务,例如 Flurry 或 Google Analytics。问题是:什么样的软件设计(松耦合、高内聚、易于维护)才能使用这些服务?

这是我的个人项目,我用它来研究新技术和最佳实践。我无意中遇到了这个“挑战”,但找不到真正的最佳解决方案。

我已经开发了一些使用这种服务的移动应用程序,通常我会实现适配器 + 工厂设计模式的组合:

  • 代表通用分析服务的基本接口(interface)已创建

    public interface IAnalytics {
    void LogEvent(string name, object param);
    }
  • 每个服务(Flurry/Google Analytics/等)API 都通过使用实现此接口(interface)的适配器进行封装​​

    public class FlurryService : IAnalyticsService {
    public LogEvent(sring name, object param) {
    Flurry.Log(name, param.ToString());
    }
    }
  • 实现工厂,以便我们在该特定应用程序上拥有所需的任何分析服务

    public static class AnalyticsServiceFactory {
    public IAnalytics CreateService(string servicename) {
    if(servicename == "google") {
    return new GoogleAnalyticsService();
    } else {
    return new FlurryService();
    }
    }
    }
  • 最后,创建了一个“代理”对象(不是书上写的)来记录特定于应用程序的事件

    public class MyAnalytics {
    private static IAnalyticsService _Service = AnalyticsServiceFactory.CreateService("flurry");

    public static void LogUserLoggedIn(string user) {
    _Service.LogEvent("login", user);
    }

    public static void LogLoginFailed(string user) {
    _Service.LogEvent("login", user);
    }
    }

这处理了每个服务 API 的封装并且效果很好,特别是在不同平台之间共享代码的应用程序中。

然而,还有一个问题是事件(或用户完成的操作)本身的记录。在我处理过的所有情况下,事件的记录在此类事件发生的任何地方都是硬编码的。例如:

public void LogIn(string userName, string pass) {
bool success = this.Controller.LogIn(userName, pass);

if(success) {
MyAnalytics.LogUserLoggedIn(username);

// Change view

} else {
MyAnalytics.LogLogInFailed(username);

// Alert
}
}

这似乎比我希望的更加耦合,所以我正在寻找更好的解决方案。

当我使用 iOS 时,我考虑过使用 NSNotificationCenter :每当事件发生时,我不会立即记录它,而是在 NSNotificationCenter 中发布通知,观察这些通知的另一个对象负责调用 MyAnalytics 来记录事件。然而,这种设计只适用于 iOS(也就是说,没有大量的工作)。

看待这个问题的另一种方式是:游戏如何跟踪您的行为以获得 Xbox 成就/Playstation 奖杯?

最佳答案

这是我通常用于可以是多提供商的日志记录类的设计。它允许在分析、崩溃报告和测试版 OTA 提供商之间轻松交换,并且它使用预处理器指令,以便某些服务在某些环境中处于事件状态。此示例使用 CocoaLumberjack,但您可以使其与您选择的日志记录框架一起使用。

@class CLLocation;

@interface TGLogger : NSObject

+ (void)startLogging;
+ (void)stopLogging;

+ (NSString *)getUdidKey;

+ (void)setUserID:(NSString *)userID;
+ (void)setUsername:(NSString *)username;
+ (void)setUserEmail:(NSString *)email;
+ (void)setUserAge:(NSUInteger)age;
+ (void)setUserGender:(NSString *)gender;
+ (void)setUserLocation:(CLLocation *)location;
+ (void)setUserValue:(NSString *)value forKey:(NSString *)key;
+ (void)setIntValue:(int)value forKey:(NSString *)key;
+ (void)setFloatValue:(float)value forKey:(NSString *)key;
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key;

extern void TGReportMilestone(NSString *milestone, NSDictionary *parameters);
extern void TGReportBeginTimedMilestone(NSString *milestone, NSDictionary *parameters);
extern void TGReportEndTimedMilestone(NSString *milestone, NSDictionary *parameters);

@end

现在是实现文件:

#import "TGLogger.h"
#import "TGAppDelegate.h"
#import <CocoaLumberjack/DDASLLogger.h>
#import <CocoaLumberjack/DDTTYLogger.h>
#import <AFNetworkActivityLogger/AFNetworkActivityLogger.h>
@import CoreLocation;

#ifdef USE_CRASHLYTICS
#import <Crashlytics/Crashlytics.h>
#import <CrashlyticsLumberjack/CrashlyticsLogger.h>
#endif

#ifdef USE_FLURRY
#import <FlurrySDK/Flurry.h>
#endif

#import <Flurry.h>

@implementation TGLogger

+ (void)startLogging
{
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
[[DDTTYLogger sharedInstance] setColorsEnabled:YES];
[[DDTTYLogger sharedInstance] setForegroundColor:[UIColor blueColor] backgroundColor:nil forFlag:LOG_FLAG_INFO];
[[DDTTYLogger sharedInstance] setForegroundColor:[UIColor orangeColor] backgroundColor:nil forFlag:LOG_FLAG_WARN];
[[DDTTYLogger sharedInstance] setForegroundColor:[UIColor redColor] backgroundColor:nil forFlag:LOG_FLAG_ERROR];

[[AFNetworkActivityLogger sharedLogger] startLogging];

#ifdef DEBUG
[[AFNetworkActivityLogger sharedLogger] setLevel:AFLoggerLevelInfo];
#else
[[AFNetworkActivityLogger sharedLogger] setLevel:AFLoggerLevelWarn];
#endif


#if defined(USE_CRASHLYTICS) || defined(USE_FLURRY)
NSString *udid = [TGLogger getUdidKey];
TGLogInfo(@"Current UDID is: %@", udid);
#endif

#ifdef USE_CRASHLYTICS
// Start Crashlytics
[Crashlytics startWithAPIKey:TGCrashlyticsKey];
[Crashlytics setUserIdentifier:udid];
[DDLog addLogger:[CrashlyticsLogger sharedInstance]];
TGLogInfo(@"Crashlytics started with API Key: %@", TGCrashlyticsKey);
#endif

#ifdef USE_FLURRY
[Flurry setAppVersion:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];
[Flurry setSecureTransportEnabled:YES];
[Flurry setShowErrorInLogEnabled:YES];
[Flurry setLogLevel:FlurryLogLevelCriticalOnly];
[Flurry startSession:TGFlurryApiKey];
TGLogInfo(@"Flurry started with API Key %@ and for version %@", TGFlurryApiKey, [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
TGLogInfo(@"Flurry Agent Version %@", [Flurry getFlurryAgentVersion]);
#endif

TGLogInfo(@"Logging services started");
}
+ (void)stopLogging
{
TGLogInfo(@"Shutting down logging services");
[DDLog removeAllLoggers];
}

+ (NSString *)getUdidKey
{
return [[UIDevice currentDevice] identifierForVendor].UUIDString;
}

+ (void)setUserID:(NSString *)userID
{
#ifdef USE_CRASHLYTICS
[Crashlytics setUserIdentifier:userID];
#endif
}

+ (void)setUsername:(NSString *)username
{
#ifdef USE_CRASHLYTICS
[Crashlytics setUserName:username];
#endif

#ifdef USE_FLURRY
[Flurry setUserID:username];
#endif

}

+ (void)setUserEmail:(NSString *)email
{
#ifdef USE_CRASHLYTICS
[Crashlytics setUserEmail:email];
#endif

}

+ (void)setUserAge:(NSUInteger)age
{
#ifdef USE_FLURRY
[Flurry setAge:(int)age];
#endif

}

+ (void)setUserGender:(NSString *)gender
{
#ifdef USE_FLURRY
[Flurry setGender:gender];
#endif
}

+ (void)setUserLocation:(CLLocation *)location
{
#ifdef USE_FLURRY
[Flurry setLatitude:location.coordinate.latitude longitude:location.coordinate.longitude horizontalAccuracy:location.horizontalAccuracy verticalAccuracy:location.verticalAccuracy];
#endif
#ifdef USE_CRASHLYTICS
[Crashlytics setObjectValue:location forKey:@"location"];
#endif
}

+ (void)setUserValue:(NSString *)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setObjectValue:value forKey:key];
#endif
}

#pragma mark - Report key/values with crash logs

+ (void)setIntValue:(int)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setIntValue:value forKey:key];
#endif
}

+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setBoolValue:value forKey:key];
#endif
}

+ (void)setFloatValue:(float)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setFloatValue:value forKey:key];
#endif
}

void TGReportMilestone(NSString *milestone, NSDictionary *parameters)
{
NSCParameterAssert(milestone);
TGLogCInfo(@"Reporting %@", milestone);

#ifdef USE_FLURRY
[Flurry logEvent:milestone withParameters:parameters];
#endif
}

void TGReportBeginTimedMilestone(NSString *milestone, NSDictionary *parameters)
{
NSCParameterAssert(milestone);
TGLogCInfo(@"Starting timed event %@", milestone);

#ifdef USE_FLURRY
[Flurry logEvent:milestone withParameters:parameters timed:YES];
#endif
}

void TGReportEndTimedMilestone(NSString *milestone, NSDictionary *parameters)
{
NSCParameterAssert(milestone);
TGLogCInfo(@"Ending timed event %@", milestone);

#ifdef USE_FLURRY
[Flurry endTimedEvent:milestone withParameters:parameters];
#endif
}


@end

关于ios - 与分析服务集成的架构/设计模式(flurry/google analytics),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23483798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com