Merge branch 'release/2.2.2'

* release/2.2.2:
  Some more 2 space indentation fixes
  fix example
  Set the delegate for Hockey and Quincy
  Remove unit test files and target
  Add appstore detection property
  Add workaround for not requiring -all_load linker flag and some Xcode project adjustments
  Updated manager for quincy logging and new delegate
  One more 2 space indentation fixes
  Add new delegate which fires when the user selected "Send Always" in the alert
  Fix for an older commit in QuincyKit being only half complete
  Don't treat empty server responses as success
  Added optional logging for debugging help
  set HOCKEYLIB_STATIC_LIBRARY define
  as a library, build for armv6 & armv7
  add xcworkspacedata
  add default xcodeproj
  Removing returning shared instance before dispatch_once is invoked
This commit is contained in:
Andreas Linde 2011-12-13 18:46:41 +01:00
commit 92f531b5f9
17 changed files with 859 additions and 397 deletions

1
.gitignore vendored
View File

@ -7,7 +7,6 @@ build/*
*.perspective *.perspective
*.perspectivev3 *.perspectivev3
!default.perspectivev3 !default.perspectivev3
*.xcworkspace
!default.xcworkspace !default.xcworkspace
xcuserdata xcuserdata
profile profile

View File

@ -36,10 +36,10 @@ NSBundle *hockeyBundle(void) {
} }
NSString *BWmd5(NSString *str) { NSString *BWmd5(NSString *str) {
const char *cStr = [str UTF8String]; const char *cStr = [str UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH]; unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, strlen(cStr), result ); CC_MD5( cStr, strlen(cStr), result );
return [NSString return [NSString
stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[0], result[1],
result[2], result[3], result[2], result[3],

View File

@ -123,8 +123,6 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain";
static BWHockeyManager *sharedInstance = nil; static BWHockeyManager *sharedInstance = nil;
static dispatch_once_t pred; static dispatch_once_t pred;
if (sharedInstance) return sharedInstance;
dispatch_once(&pred, ^{ dispatch_once(&pred, ^{
sharedInstance = [BWHockeyManager alloc]; sharedInstance = [BWHockeyManager alloc];
sharedInstance = [sharedInstance init]; sharedInstance = [sharedInstance init];

View File

@ -62,7 +62,7 @@
} }
- (id)init { - (id)init {
return [self init:[BWHockeyManager sharedHockeyManager]]; return [self init:[BWHockeyManager sharedHockeyManager]];
} }
#pragma mark - #pragma mark -

View File

@ -295,26 +295,26 @@
} }
- (CAGradientLayer *)backgroundLayer { - (CAGradientLayer *)backgroundLayer {
UIColor *colorOne = [UIColor colorWithWhite:0.9 alpha:1.0]; UIColor *colorOne = [UIColor colorWithWhite:0.9 alpha:1.0];
UIColor *colorTwo = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.85 alpha:1.0]; UIColor *colorTwo = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.85 alpha:1.0];
UIColor *colorThree = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.7 alpha:1.0]; UIColor *colorThree = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.7 alpha:1.0];
UIColor *colorFour = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.4 alpha:1.0]; UIColor *colorFour = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.4 alpha:1.0];
NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, colorThree.CGColor, colorFour.CGColor, nil]; NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, colorThree.CGColor, colorFour.CGColor, nil];
NSNumber *stopOne = [NSNumber numberWithFloat:0.0]; NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
NSNumber *stopTwo = [NSNumber numberWithFloat:0.02]; NSNumber *stopTwo = [NSNumber numberWithFloat:0.02];
NSNumber *stopThree = [NSNumber numberWithFloat:0.99]; NSNumber *stopThree = [NSNumber numberWithFloat:0.99];
NSNumber *stopFour = [NSNumber numberWithFloat:1.0]; NSNumber *stopFour = [NSNumber numberWithFloat:1.0];
NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, stopThree, stopFour, nil]; NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, stopThree, stopFour, nil];
CAGradientLayer *headerLayer = [CAGradientLayer layer]; CAGradientLayer *headerLayer = [CAGradientLayer layer];
//headerLayer.frame = CGRectMake(0.0, 0.0, 320.0, 77.0); //headerLayer.frame = CGRectMake(0.0, 0.0, 320.0, 77.0);
headerLayer.colors = colors; headerLayer.colors = colors;
headerLayer.locations = locations; headerLayer.locations = locations;
return headerLayer; return headerLayer;
} }
- (void)viewDidLoad { - (void)viewDidLoad {

View File

@ -29,6 +29,8 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#define BWQuincyLog(fmt, ...) do { if([BWQuincyManager sharedQuincyManager].isLoggingEnabled) { NSLog((@"[QuincyLib] %s/%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); }} while(0)
#define kQuincyBundleName @"Quincy.bundle" #define kQuincyBundleName @"Quincy.bundle"
NSBundle *quincyBundle(void); NSBundle *quincyBundle(void);
@ -52,31 +54,31 @@ NSString *BWQuincyLocalize(NSString *stringToken);
#define BWQuincyNetworkBecomeReachable @"NetworkDidBecomeReachable" #define BWQuincyNetworkBecomeReachable @"NetworkDidBecomeReachable"
typedef enum QuincyKitAlertType { typedef enum QuincyKitAlertType {
QuincyKitAlertTypeSend = 0, QuincyKitAlertTypeSend = 0,
QuincyKitAlertTypeFeedback = 1, QuincyKitAlertTypeFeedback = 1,
} CrashAlertType; } CrashAlertType;
typedef enum CrashReportStatus { typedef enum CrashReportStatus {
// The status of the crash is queued, need to check later (HockeyApp) // The status of the crash is queued, need to check later (HockeyApp)
CrashReportStatusQueued = -80, CrashReportStatusQueued = -80,
// This app version is set to discontinued, no new crash reports accepted by the server // This app version is set to discontinued, no new crash reports accepted by the server
CrashReportStatusFailureVersionDiscontinued = -30, CrashReportStatusFailureVersionDiscontinued = -30,
// XML: Sender version string contains not allowed characters, only alphanumberical including space and . are allowed // XML: Sender version string contains not allowed characters, only alphanumberical including space and . are allowed
CrashReportStatusFailureXMLSenderVersionNotAllowed = -21, CrashReportStatusFailureXMLSenderVersionNotAllowed = -21,
// XML: Version string contains not allowed characters, only alphanumberical including space and . are allowed // XML: Version string contains not allowed characters, only alphanumberical including space and . are allowed
CrashReportStatusFailureXMLVersionNotAllowed = -20, CrashReportStatusFailureXMLVersionNotAllowed = -20,
// SQL for adding a symoblicate todo entry in the database failed // SQL for adding a symoblicate todo entry in the database failed
CrashReportStatusFailureSQLAddSymbolicateTodo = -18, CrashReportStatusFailureSQLAddSymbolicateTodo = -18,
// SQL for adding crash log in the database failed // SQL for adding crash log in the database failed
CrashReportStatusFailureSQLAddCrashlog = -17, CrashReportStatusFailureSQLAddCrashlog = -17,
// SQL for adding a new version in the database failed // SQL for adding a new version in the database failed
CrashReportStatusFailureSQLAddVersion = -16, CrashReportStatusFailureSQLAddVersion = -16,
// SQL for checking if the version is already added in the database failed // SQL for checking if the version is already added in the database failed
CrashReportStatusFailureSQLCheckVersionExists = -15, CrashReportStatusFailureSQLCheckVersionExists = -15,
@ -137,6 +139,9 @@ typedef enum CrashReportStatus {
// Invoked before the user is asked to send a crash report, so you can do additional actions. E.g. to make sure not to ask the user for an app rating :) // Invoked before the user is asked to send a crash report, so you can do additional actions. E.g. to make sure not to ask the user for an app rating :)
-(void) willShowSubmitCrashReportAlert; -(void) willShowSubmitCrashReportAlert;
// Invoked after the user did choose to send crashes always in the alert
-(void) userDidChooseSendAlways;
@end @end
@interface BWQuincyManager : NSObject <NSXMLParserDelegate> { @interface BWQuincyManager : NSObject <NSXMLParserDelegate> {
@ -144,6 +149,7 @@ typedef enum CrashReportStatus {
id <BWQuincyManagerDelegate> _delegate; id <BWQuincyManagerDelegate> _delegate;
BOOL _loggingEnabled;
BOOL _showAlwaysButton; BOOL _showAlwaysButton;
BOOL _feedbackActivated; BOOL _feedbackActivated;
BOOL _autoSubmitCrashReport; BOOL _autoSubmitCrashReport;
@ -156,19 +162,19 @@ typedef enum CrashReportStatus {
NSString *_feedbackRequestID; NSString *_feedbackRequestID;
float _feedbackDelayInterval; float _feedbackDelayInterval;
NSMutableString *_contentOfProperty; NSMutableString *_contentOfProperty;
CrashReportStatus _serverResult; CrashReportStatus _serverResult;
int _analyzerStarted; int _analyzerStarted;
NSString *_crashesDir; NSString *_crashesDir;
BOOL _crashIdenticalCurrentVersion; BOOL _crashIdenticalCurrentVersion;
BOOL _crashReportActivated; BOOL _crashReportActivated;
NSMutableArray *_crashFiles; NSMutableArray *_crashFiles;
NSMutableData *_responseData; NSMutableData *_responseData;
NSInteger _statusCode; NSInteger _statusCode;
NSURLConnection *_urlConnection; NSURLConnection *_urlConnection;
@ -189,6 +195,10 @@ typedef enum CrashReportStatus {
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// settings // settings
// if YES, states will be logged using NSLog. Only enable this for debugging!
// if NO, nothing will be logged. (default)
@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled;
// nil, using the default localization files (Default) // nil, using the default localization files (Default)
// set to another string which will be appended to the Quincy localization file name, "Alternate" is another provided text set // set to another string which will be appended to the Quincy localization file name, "Alternate" is another provided text set
@property (nonatomic, retain) NSString *languageStyle; @property (nonatomic, retain) NSString *languageStyle;

View File

@ -87,12 +87,12 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
@synthesize autoSubmitDeviceUDID = _autoSubmitDeviceUDID; @synthesize autoSubmitDeviceUDID = _autoSubmitDeviceUDID;
@synthesize languageStyle = _languageStyle; @synthesize languageStyle = _languageStyle;
@synthesize didCrashInLastSession = _didCrashInLastSession; @synthesize didCrashInLastSession = _didCrashInLastSession;
@synthesize loggingEnabled = _loggingEnabled;
@synthesize appIdentifier = _appIdentifier; @synthesize appIdentifier = _appIdentifier;
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000
+(BWQuincyManager *)sharedQuincyManager +(BWQuincyManager *)sharedQuincyManager {
{
static BWQuincyManager *sharedInstance = nil; static BWQuincyManager *sharedInstance = nil;
static dispatch_once_t pred; static dispatch_once_t pred;
@ -105,86 +105,87 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
} }
#else #else
+ (BWQuincyManager *)sharedQuincyManager { + (BWQuincyManager *)sharedQuincyManager {
static BWQuincyManager *quincyManager = nil; static BWQuincyManager *quincyManager = nil;
if (quincyManager == nil) { if (quincyManager == nil) {
quincyManager = [[BWQuincyManager alloc] init]; quincyManager = [[BWQuincyManager alloc] init];
} }
return quincyManager; return quincyManager;
} }
#endif #endif
- (id) init { - (id) init {
if ((self = [super init])) { if ((self = [super init])) {
_serverResult = CrashReportStatusUnknown; _serverResult = CrashReportStatusUnknown;
_crashIdenticalCurrentVersion = YES; _crashIdenticalCurrentVersion = YES;
_crashData = nil; _crashData = nil;
_urlConnection = nil; _urlConnection = nil;
_submissionURL = nil; _submissionURL = nil;
_responseData = nil; _responseData = nil;
_appIdentifier = nil; _appIdentifier = nil;
_sendingInProgress = NO; _sendingInProgress = NO;
_languageStyle = nil; _languageStyle = nil;
_didCrashInLastSession = NO; _didCrashInLastSession = NO;
_loggingEnabled = NO;
self.delegate = nil; self.delegate = nil;
self.feedbackActivated = NO; self.feedbackActivated = NO;
self.showAlwaysButton = NO; self.showAlwaysButton = NO;
self.autoSubmitCrashReport = NO; self.autoSubmitCrashReport = NO;
self.autoSubmitDeviceUDID = NO; self.autoSubmitDeviceUDID = NO;
NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitAnalyzerStarted]; NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitAnalyzerStarted];
if (testValue) { if (testValue) {
_analyzerStarted = [[NSUserDefaults standardUserDefaults] integerForKey:kQuincyKitAnalyzerStarted]; _analyzerStarted = [[NSUserDefaults standardUserDefaults] integerForKey:kQuincyKitAnalyzerStarted];
} else { } else {
_analyzerStarted = 0; _analyzerStarted = 0;
} }
testValue = nil; testValue = nil;
testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitActivated]; testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitActivated];
if (testValue) { if (testValue) {
_crashReportActivated = [[NSUserDefaults standardUserDefaults] boolForKey:kQuincyKitActivated]; _crashReportActivated = [[NSUserDefaults standardUserDefaults] boolForKey:kQuincyKitActivated];
} else { } else {
_crashReportActivated = YES; _crashReportActivated = YES;
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kQuincyKitActivated]; [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kQuincyKitActivated];
} }
if (_crashReportActivated) { if (_crashReportActivated) {
_crashFiles = [[NSMutableArray alloc] init]; _crashFiles = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
_crashesDir = [[NSString stringWithFormat:@"%@", [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/crashes/"]] retain]; _crashesDir = [[NSString stringWithFormat:@"%@", [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/crashes/"]] retain];
NSFileManager *fm = [NSFileManager defaultManager]; NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:_crashesDir]) { if (![fm fileExistsAtPath:_crashesDir]) {
NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions]; NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions];
NSError *theError = NULL; NSError *theError = NULL;
[fm createDirectoryAtPath:_crashesDir withIntermediateDirectories: YES attributes: attributes error: &theError]; [fm createDirectoryAtPath:_crashesDir withIntermediateDirectories: YES attributes: attributes error: &theError];
}
PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
NSError *error = NULL;
// Check if we previously crashed
if ([crashReporter hasPendingCrashReport]) {
_didCrashInLastSession = YES;
[self handleCrashReport];
} }
// Enable the Crash Reporter PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
if (![crashReporter enableCrashReporterAndReturnError: &error]) NSError *error = NULL;
NSLog(@"Warning: Could not enable crash reporter: %@", error);
// Check if we previously crashed
if ([crashReporter hasPendingCrashReport]) {
_didCrashInLastSession = YES;
[self handleCrashReport];
}
// Enable the Crash Reporter
if (![crashReporter enableCrashReporterAndReturnError: &error])
NSLog(@"WARNING: Could not enable crash reporter: %@", error);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startManager) name:BWQuincyNetworkBecomeReachable object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startManager) name:BWQuincyNetworkBecomeReachable object:nil];
} }
if (!quincyBundle()) { if (!quincyBundle()) {
NSLog(@"WARNING: Quincy.bundle is missing in the app bundle!"); NSLog(@"WARNING: Quincy.bundle is missing, will send reports automatically!");
} }
} }
return self; return self;
} }
@ -206,10 +207,10 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
[_crashData release]; [_crashData release];
[_crashesDir release]; [_crashesDir release];
[_crashFiles release]; [_crashFiles release];
[super dealloc]; [super dealloc];
} }
@ -256,9 +257,9 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
if (!_sendingInProgress && [self hasPendingCrashReport]) { if (!_sendingInProgress && [self hasPendingCrashReport]) {
_sendingInProgress = YES; _sendingInProgress = YES;
if (!quincyBundle()) { if (!quincyBundle()) {
NSLog(@"Quincy.bundle is missing, sending report automatically!"); NSLog(@"WARNING: Quincy.bundle is missing, sending reports automatically!");
[self _sendCrashReports]; [self _sendCrashReports];
} else if (!self.autoSubmitCrashReport && [self hasNonApprovedCrashReports]) { } else if (![self autoSendCrashReports] && [self hasNonApprovedCrashReports]) {
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(willShowSubmitCrashReportAlert)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(willShowSubmitCrashReportAlert)]) {
[self.delegate willShowSubmitCrashReportAlert]; [self.delegate willShowSubmitCrashReportAlert];
@ -290,8 +291,8 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
if (!approvedCrashReports || [approvedCrashReports count] == 0) return YES; if (!approvedCrashReports || [approvedCrashReports count] == 0) return YES;
for (NSUInteger i=0; i < [_crashFiles count]; i++) { for (NSUInteger i=0; i < [_crashFiles count]; i++) {
NSString *filename = [_crashFiles objectAtIndex:i]; NSString *filename = [_crashFiles objectAtIndex:i];
if (![approvedCrashReports objectForKey:filename]) return YES; if (![approvedCrashReports objectForKey:filename]) return YES;
} }
@ -300,73 +301,74 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
} }
- (BOOL)hasPendingCrashReport { - (BOOL)hasPendingCrashReport {
if (_crashReportActivated) { if (_crashReportActivated) {
NSFileManager *fm = [NSFileManager defaultManager]; NSFileManager *fm = [NSFileManager defaultManager];
if ([_crashFiles count] == 0 && [fm fileExistsAtPath:_crashesDir]) { if ([_crashFiles count] == 0 && [fm fileExistsAtPath:_crashesDir]) {
NSString *file = nil; NSString *file = nil;
NSError *error = NULL; NSError *error = NULL;
NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath: _crashesDir]; NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath: _crashesDir];
while ((file = [dirEnum nextObject])) { while ((file = [dirEnum nextObject])) {
NSDictionary *fileAttributes = [fm attributesOfItemAtPath:[_crashesDir stringByAppendingPathComponent:file] error:&error]; NSDictionary *fileAttributes = [fm attributesOfItemAtPath:[_crashesDir stringByAppendingPathComponent:file] error:&error];
if ([[fileAttributes objectForKey:NSFileSize] intValue] > 0) { if ([[fileAttributes objectForKey:NSFileSize] intValue] > 0) {
[_crashFiles addObject:file]; [_crashFiles addObject:file];
} }
} }
} }
if ([_crashFiles count] > 0) { if ([_crashFiles count] > 0) {
return YES; BWQuincyLog(@"Pending crash reports found.");
} else return YES;
return NO; } else
} else return NO;
return NO; } else
return NO;
} }
- (void) showCrashStatusMessage { - (void) showCrashStatusMessage {
UIAlertView *alertView = nil; UIAlertView *alertView = nil;
if (_serverResult >= CrashReportStatusAssigned && if (_serverResult >= CrashReportStatusAssigned &&
_crashIdenticalCurrentVersion && _crashIdenticalCurrentVersion &&
quincyBundle()) { quincyBundle()) {
// show some feedback to the user about the crash status // show some feedback to the user about the crash status
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
switch (_serverResult) { switch (_serverResult) {
case CrashReportStatusAssigned: case CrashReportStatusAssigned:
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ] alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ]
message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseNextRelease"), appName] message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseNextRelease"), appName]
delegate: self delegate: self
cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK") cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK")
otherButtonTitles: nil]; otherButtonTitles: nil];
break; break;
case CrashReportStatusSubmitted: case CrashReportStatusSubmitted:
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ] alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ]
message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseWaitingApple"), appName] message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseWaitingApple"), appName]
delegate: self delegate: self
cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK") cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK")
otherButtonTitles: nil]; otherButtonTitles: nil];
break; break;
case CrashReportStatusAvailable: case CrashReportStatusAvailable:
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ] alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ]
message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseAvailable"), appName] message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseAvailable"), appName]
delegate: self delegate: self
cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK") cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK")
otherButtonTitles: nil]; otherButtonTitles: nil];
break; break;
default: default:
alertView = nil; alertView = nil;
break; break;
} }
if (alertView) { if (alertView) {
[alertView setTag: QuincyKitAlertTypeFeedback]; [alertView setTag: QuincyKitAlertTypeFeedback];
[alertView show]; [alertView show];
[alertView release]; [alertView release];
} }
} }
} }
@ -374,22 +376,31 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
#pragma mark UIAlertView Delegate #pragma mark UIAlertView Delegate
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if ([alertView tag] == QuincyKitAlertTypeSend) { if ([alertView tag] == QuincyKitAlertTypeSend) {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
_sendingInProgress = NO; _sendingInProgress = NO;
[self _cleanCrashReports]; [self _cleanCrashReports];
break; break;
case 1: case 1:
[self _sendCrashReports]; [self _sendCrashReports];
break; break;
case 2: case 2: {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAutomaticallySendCrashReports]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAutomaticallySendCrashReports];
[[NSUserDefaults standardUserDefaults] synchronize];
[self _sendCrashReports]; if (self.delegate != nil && [self.delegate respondsToSelector:@selector(userDidChooseSendAlways)]) {
break; [self.delegate userDidChooseSendAlways];
} }
}
[self _sendCrashReports];
break;
}
default:
_sendingInProgress = NO;
[self _cleanCrashReports];
break;
}
}
} }
#pragma mark - #pragma mark -
@ -398,40 +409,40 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
#pragma mark NSXMLParser #pragma mark NSXMLParser
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if (qName) { if (qName) {
elementName = qName; elementName = qName;
} }
if ([elementName isEqualToString:@"result"]) { if ([elementName isEqualToString:@"result"]) {
_contentOfProperty = [NSMutableString string]; _contentOfProperty = [NSMutableString string];
} }
} }
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if (qName) { if (qName) {
elementName = qName; elementName = qName;
} }
// open source implementation // open source implementation
if ([elementName isEqualToString: @"result"]) { if ([elementName isEqualToString: @"result"]) {
if ([_contentOfProperty intValue] > _serverResult) { if ([_contentOfProperty intValue] > _serverResult) {
_serverResult = (CrashReportStatus)[_contentOfProperty intValue]; _serverResult = (CrashReportStatus)[_contentOfProperty intValue];
} else { } else {
CrashReportStatus errorcode = (CrashReportStatus)[_contentOfProperty intValue]; CrashReportStatus errorcode = (CrashReportStatus)[_contentOfProperty intValue];
NSLog(@"CrashReporter ended in error code: %i", errorcode); NSLog(@"CrashReporter ended in error code: %i", errorcode);
} }
} }
} }
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (_contentOfProperty) { if (_contentOfProperty) {
// If the current element is one whose content we care about, append 'string' // If the current element is one whose content we care about, append 'string'
// to the property that holds the content of the current element. // to the property that holds the content of the current element.
if (string != nil) { if (string != nil) {
[_contentOfProperty appendString:string]; [_contentOfProperty appendString:string];
} }
} }
} }
#pragma mark - #pragma mark -
@ -439,13 +450,13 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
- (NSString *)_getDevicePlatform { - (NSString *)_getDevicePlatform {
size_t size = 0; size_t size = 0;
sysctlbyname("hw.machine", NULL, &size, NULL, 0); sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *answer = (char*)malloc(size); char *answer = (char*)malloc(size);
sysctlbyname("hw.machine", answer, &size, NULL, 0); sysctlbyname("hw.machine", answer, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding]; NSString *platform = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
free(answer); free(answer);
return platform; return platform;
} }
- (NSString *)deviceIdentifier { - (NSString *)deviceIdentifier {
@ -461,52 +472,52 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
NSMutableDictionary *approvedCrashReports = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey: kApprovedCrashReports]]; NSMutableDictionary *approvedCrashReports = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey: kApprovedCrashReports]];
NSFileManager *fm = [NSFileManager defaultManager]; NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = NULL; NSError *error = NULL;
NSString *userid = @""; NSString *userid = @"";
NSString *contact = @""; NSString *contact = @"";
NSString *description = @""; NSString *description = @"";
if (self.autoSubmitDeviceUDID && [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]) { if (self.autoSubmitDeviceUDID && [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]) {
userid = [self deviceIdentifier]; userid = [self deviceIdentifier];
} else if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportUserID)]) { } else if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportUserID)]) {
userid = [self.delegate crashReportUserID] ?: @""; userid = [self.delegate crashReportUserID] ?: @"";
} }
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportContact)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportContact)]) {
contact = [self.delegate crashReportContact] ?: @""; contact = [self.delegate crashReportContact] ?: @"";
} }
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportDescription)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportDescription)]) {
description = [self.delegate crashReportDescription] ?: @""; description = [self.delegate crashReportDescription] ?: @"";
} }
NSMutableString *crashes = nil; NSMutableString *crashes = nil;
_crashIdenticalCurrentVersion = NO; _crashIdenticalCurrentVersion = NO;
for (NSUInteger i=0; i < [_crashFiles count]; i++) { for (NSUInteger i=0; i < [_crashFiles count]; i++) {
NSString *filename = [_crashesDir stringByAppendingPathComponent:[_crashFiles objectAtIndex:i]]; NSString *filename = [_crashesDir stringByAppendingPathComponent:[_crashFiles objectAtIndex:i]];
NSData *crashData = [NSData dataWithContentsOfFile:filename]; NSData *crashData = [NSData dataWithContentsOfFile:filename];
if ([crashData length] > 0) { if ([crashData length] > 0) {
PLCrashReport *report = [[[PLCrashReport alloc] initWithData:crashData error:&error] autorelease]; PLCrashReport *report = [[[PLCrashReport alloc] initWithData:crashData error:&error] autorelease];
if (report == nil) { if (report == nil) {
NSLog(@"Could not parse crash report"); NSLog(@"Could not parse crash report");
continue; continue;
} }
NSString *crashLogString = [PLCrashReportTextFormatter stringValueForCrashReport:report withTextFormat:PLCrashReportTextFormatiOS]; NSString *crashLogString = [PLCrashReportTextFormatter stringValueForCrashReport:report withTextFormat:PLCrashReportTextFormatiOS];
if ([report.applicationInfo.applicationVersion compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) { if ([report.applicationInfo.applicationVersion compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
_crashIdenticalCurrentVersion = YES; _crashIdenticalCurrentVersion = YES;
} }
if (crashes == nil) { if (crashes == nil) {
crashes = [NSMutableString string]; crashes = [NSMutableString string];
} }
[crashes appendFormat:@"<crash><applicationname>%s</applicationname><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><log><![CDATA[%@]]></log><userid>%@</userid><contact>%@</contact><description><![CDATA[%@]]></description></crash>", [crashes appendFormat:@"<crash><applicationname>%s</applicationname><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><log><![CDATA[%@]]></log><userid>%@</userid><contact>%@</contact><description><![CDATA[%@]]></description></crash>",
[[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"] UTF8String], [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"] UTF8String],
report.applicationInfo.applicationIdentifier, report.applicationInfo.applicationIdentifier,
report.systemInfo.operatingSystemVersion, report.systemInfo.operatingSystemVersion,
@ -516,21 +527,22 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
[crashLogString stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,crashLogString.length)], [crashLogString stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,crashLogString.length)],
userid, userid,
contact, contact,
[description stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,description.length)]]; [description stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,description.length)]];
// store this crash report as user approved, so if it fails it will retry automatically // store this crash report as user approved, so if it fails it will retry automatically
[approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:[_crashFiles objectAtIndex:i]]; [approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:[_crashFiles objectAtIndex:i]];
} else { } else {
// we cannot do anything with this report, so delete it // we cannot do anything with this report, so delete it
[fm removeItemAtPath:filename error:&error]; [fm removeItemAtPath:filename error:&error];
} }
} }
[[NSUserDefaults standardUserDefaults] setObject:approvedCrashReports forKey:kApprovedCrashReports]; [[NSUserDefaults standardUserDefaults] setObject:approvedCrashReports forKey:kApprovedCrashReports];
[[NSUserDefaults standardUserDefaults] synchronize]; [[NSUserDefaults standardUserDefaults] synchronize];
if (crashes != nil) { if (crashes != nil) {
BWQuincyLog(@"Sending crash reports:\n%@", crashes);
[self _postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes] [self _postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes]
toURL:[NSURL URLWithString:self.submissionURL]]; toURL:[NSURL URLWithString:self.submissionURL]];
@ -559,56 +571,60 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
- (void)_checkForFeedbackStatus { - (void)_checkForFeedbackStatus {
NSMutableURLRequest *request = nil; NSMutableURLRequest *request = nil;
request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes/%@", request = [NSMutableURLRequest requestWithURL:
self.submissionURL, [NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes/%@",
[self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], self.submissionURL,
_feedbackRequestID [self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
] _feedbackRequestID
]]; ]
]];
[request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData]; [request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData];
[request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"]; [request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"];
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
[request setTimeoutInterval: 15]; [request setTimeoutInterval: 15];
[request setHTTPMethod:@"GET"]; [request setHTTPMethod:@"GET"];
_serverResult = CrashReportStatusUnknown; _serverResult = CrashReportStatusUnknown;
_statusCode = 200; _statusCode = 200;
// Release when done in the delegate method // Release when done in the delegate method
_responseData = [[NSMutableData alloc] init]; _responseData = [[NSMutableData alloc] init];
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) {
[self.delegate connectionOpened]; [self.delegate connectionOpened];
} }
_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
BWQuincyLog(@"Requesting feedback status.");
} }
- (void)_postXML:(NSString*)xml toURL:(NSURL*)url { - (void)_postXML:(NSString*)xml toURL:(NSURL*)url {
NSMutableURLRequest *request = nil; NSMutableURLRequest *request = nil;
NSString *boundary = @"----FOO"; NSString *boundary = @"----FOO";
if (self.appIdentifier) { if (self.appIdentifier) {
request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes", request = [NSMutableURLRequest requestWithURL:
self.submissionURL, [NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes",
[self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] self.submissionURL,
] [self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
]]; ]
]];
} else { } else {
request = [NSMutableURLRequest requestWithURL:url]; request = [NSMutableURLRequest requestWithURL:url];
} }
[request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData]; [request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData];
[request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"]; [request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"];
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
[request setTimeoutInterval: 15]; [request setTimeoutInterval: 15];
[request setHTTPMethod:@"POST"]; [request setHTTPMethod:@"POST"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField:@"Content-type"]; [request setValue:contentType forHTTPHeaderField:@"Content-type"];
NSMutableData *postBody = [NSMutableData data]; NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
if (self.appIdentifier) { if (self.appIdentifier) {
[postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
@ -620,49 +636,54 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
[request setHTTPBody:postBody]; [request setHTTPBody:postBody];
_serverResult = CrashReportStatusUnknown; _serverResult = CrashReportStatusUnknown;
_statusCode = 200; _statusCode = 200;
//Release when done in the delegate method //Release when done in the delegate method
_responseData = [[NSMutableData alloc] init]; _responseData = [[NSMutableData alloc] init];
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) {
[self.delegate connectionOpened]; [self.delegate connectionOpened];
} }
_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (!_urlConnection) { if (!_urlConnection) {
BWQuincyLog(@"Sending crash reports could not start!");
_sendingInProgress = NO; _sendingInProgress = NO;
} else {
BWQuincyLog(@"Sending crash reports started.");
} }
} }
#pragma mark NSURLConnection Delegate #pragma mark NSURLConnection Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) { if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
_statusCode = [(NSHTTPURLResponse *)response statusCode]; _statusCode = [(NSHTTPURLResponse *)response statusCode];
} }
} }
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[_responseData appendData:data]; [_responseData appendData:data];
} }
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[_responseData release]; [_responseData release];
_responseData = nil; _responseData = nil;
_urlConnection = nil; _urlConnection = nil;
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) {
[self.delegate connectionClosed]; [self.delegate connectionClosed];
} }
BWQuincyLog(@"ERROR: %@", [error localizedDescription]);
_sendingInProgress = NO; _sendingInProgress = NO;
} }
- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (_statusCode >= 200 && _statusCode < 400) { if (_statusCode >= 200 && _statusCode < 400 && _responseData != nil && [_responseData length] > 0) {
[self _cleanCrashReports]; [self _cleanCrashReports];
_feedbackRequestID = nil; _feedbackRequestID = nil;
@ -672,6 +693,8 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
mutabilityOption:NSPropertyListMutableContainersAndLeaves mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:nil format:nil
errorDescription:NULL]; errorDescription:NULL];
BWQuincyLog(@"Received API response: %@", response);
_serverResult = (CrashReportStatus)[[response objectForKey:@"status"] intValue]; _serverResult = (CrashReportStatus)[[response objectForKey:@"status"] intValue];
if ([response objectForKey:@"id"]) { if ([response objectForKey:@"id"]) {
_feedbackRequestID = [[NSString alloc] initWithString:[response objectForKey:@"id"]]; _feedbackRequestID = [[NSString alloc] initWithString:[response objectForKey:@"id"]];
@ -680,6 +703,8 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
_feedbackDelayInterval *= 0.01; _feedbackDelayInterval *= 0.01;
} }
} else { } else {
BWQuincyLog(@"Received API response: %@", [[[NSString alloc] initWithBytes:[_responseData bytes] length:[_responseData length] encoding: NSUTF8StringEncoding] autorelease]);
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:_responseData]; NSXMLParser *parser = [[NSXMLParser alloc] initWithData:_responseData];
// Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks. // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
[parser setDelegate:self]; [parser setDelegate:self];
@ -705,15 +730,21 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
[self showCrashStatusMessage]; [self showCrashStatusMessage];
} }
} }
} } else {
if (_responseData == nil || [_responseData length] == 0) {
BWQuincyLog(@"ERROR: Sending failed with an empty response!");
} else {
BWQuincyLog(@"ERROR: Sending failed with status code: %i", _statusCode);
}
}
[_responseData release]; [_responseData release];
_responseData = nil; _responseData = nil;
_urlConnection = nil; _urlConnection = nil;
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) {
[self.delegate connectionClosed]; [self.delegate connectionClosed];
} }
_sendingInProgress = NO; _sendingInProgress = NO;
} }
@ -724,15 +755,15 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
// Called to handle a pending crash report. // Called to handle a pending crash report.
// //
- (void) handleCrashReport { - (void) handleCrashReport {
PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter]; PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
NSError *error = NULL; NSError *error = NULL;
// check if the next call ran successfully the last time // check if the next call ran successfully the last time
if (_analyzerStarted == 0) { if (_analyzerStarted == 0) {
// mark the start of the routine // mark the start of the routine
_analyzerStarted = 1; _analyzerStarted = 1;
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted]; [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted];
[[NSUserDefaults standardUserDefaults] synchronize]; [[NSUserDefaults standardUserDefaults] synchronize];
// Try loading the crash report // Try loading the crash report
_crashData = [[NSData alloc] initWithData:[crashReporter loadPendingCrashReportDataAndReturnError: &error]]; _crashData = [[NSData alloc] initWithData:[crashReporter loadPendingCrashReportDataAndReturnError: &error]];
@ -743,17 +774,17 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
NSLog(@"Could not load crash report: %@", error); NSLog(@"Could not load crash report: %@", error);
} else { } else {
[_crashData writeToFile:[_crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES]; [_crashData writeToFile:[_crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES];
} }
} }
// Purge the report // Purge the report
// mark the end of the routine // mark the end of the routine
_analyzerStarted = 0; _analyzerStarted = 0;
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted]; [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted];
[[NSUserDefaults standardUserDefaults] synchronize]; [[NSUserDefaults standardUserDefaults] synchronize];
[crashReporter purgePendingCrashReport]; [crashReporter purgePendingCrashReport];
return; return;
} }

View File

@ -0,0 +1,25 @@
//
// CNSFixCategoryBug.h
// HockeySDK
//
// Created by Andreas Linde on 12/7/11.
// Copyright (c) 2011 Andreas Linde. All rights reserved.
//
#ifndef HockeySDK_CNSFixCategoryBug_h
#define HockeySDK_CNSFixCategoryBug_h
/**
Add this macro before each category implementation, so we don't have to use
-all_load or -force_load to load object files from static libraries that only contain
categories and no classes.
See http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html for more info.
Shamelessly borrowed from Three20
*/
#define CNS_FIX_CATEGORY_BUG(name) @interface CNS_FIX_CATEGORY_BUG##name @end \
@implementation CNS_FIX_CATEGORY_BUG##name @end
#endif

View File

@ -80,6 +80,9 @@
// user for an app rating :) // user for an app rating :)
- (void)willShowSubmitCrashReportAlert; - (void)willShowSubmitCrashReportAlert;
// Invoked after the user did choose to send crashes always in the alert
-(void) userDidChooseSendAlways;
@end @end
@interface CNSHockeyManager : NSObject { @interface CNSHockeyManager : NSObject {
@ -201,6 +204,10 @@
// Default: HockeyComparisonResultGreater // Default: HockeyComparisonResultGreater
@property (nonatomic, assign) HockeyComparisonResult compareVersionType; @property (nonatomic, assign) HockeyComparisonResult compareVersionType;
// if YES the app is installed from the app store
// if NO the app is installed via ad-hoc or enterprise distribution
@property (nonatomic, readonly) BOOL isAppStoreEnvironment;
#pragma mark - Public Methods #pragma mark - Public Methods
// Returns the shared manager object // Returns the shared manager object

View File

@ -42,10 +42,6 @@
static CNSHockeyManager *sharedInstance = nil; static CNSHockeyManager *sharedInstance = nil;
static dispatch_once_t pred; static dispatch_once_t pred;
if (sharedInstance) {
return sharedInstance;
}
dispatch_once(&pred, ^{ dispatch_once(&pred, ^{
sharedInstance = [CNSHockeyManager alloc]; sharedInstance = [CNSHockeyManager alloc];
sharedInstance = [sharedInstance init]; sharedInstance = [sharedInstance init];
@ -55,13 +51,13 @@
} }
#else #else
+ (CNSHockeyManager *)sharedHockeyManager { + (CNSHockeyManager *)sharedHockeyManager {
static CNSHockeyManager *hockeyManager = nil; static CNSHockeyManager *hockeyManager = nil;
if (hockeyManager == nil) { if (hockeyManager == nil) {
hockeyManager = [[CNSHockeyManager alloc] init]; hockeyManager = [[CNSHockeyManager alloc] init];
} }
return hockeyManager; return hockeyManager;
} }
#endif #endif
@ -149,10 +145,12 @@
- (BOOL)isLoggingEnabled { - (BOOL)isLoggingEnabled {
return [[BWHockeyManager sharedHockeyManager] isLoggingEnabled]; return [[BWHockeyManager sharedHockeyManager] isLoggingEnabled];
return [[BWQuincyManager sharedQuincyManager] isLoggingEnabled];
} }
- (void)setLoggingEnabled:(BOOL)loggingEnabled { - (void)setLoggingEnabled:(BOOL)loggingEnabled {
return [[BWHockeyManager sharedHockeyManager] setLoggingEnabled:loggingEnabled]; return [[BWHockeyManager sharedHockeyManager] setLoggingEnabled:loggingEnabled];
return [[BWQuincyManager sharedQuincyManager] setLoggingEnabled:loggingEnabled];
} }
#pragma mark - Public Instance Methods (Crash Reporting) #pragma mark - Public Instance Methods (Crash Reporting)
@ -299,6 +297,10 @@
[[BWHockeyManager sharedHockeyManager] setCompareVersionType:compareVersionType]; [[BWHockeyManager sharedHockeyManager] setCompareVersionType:compareVersionType];
} }
- (BOOL)isAppStoreEnvironment {
return [[BWHockeyManager sharedHockeyManager] isAppStoreEnvironment];
}
- (BOOL)isUpdateAvailable { - (BOOL)isUpdateAvailable {
return [[BWHockeyManager sharedHockeyManager] isUpdateAvailable]; return [[BWHockeyManager sharedHockeyManager] isUpdateAvailable];
} }
@ -348,12 +350,14 @@
- (void)configureQuincyManager { - (void)configureQuincyManager {
[[BWQuincyManager sharedQuincyManager] setAppIdentifier:appIdentifier]; [[BWQuincyManager sharedQuincyManager] setAppIdentifier:appIdentifier];
[[BWQuincyManager sharedQuincyManager] setDelegate:delegate];
} }
- (void)configureHockeyManager { - (void)configureHockeyManager {
[[BWHockeyManager sharedHockeyManager] setAppIdentifier:appIdentifier]; [[BWHockeyManager sharedHockeyManager] setAppIdentifier:appIdentifier];
[[BWHockeyManager sharedHockeyManager] setCheckForTracker:YES]; [[BWHockeyManager sharedHockeyManager] setCheckForTracker:YES];
[[BWHockeyManager sharedHockeyManager] setDelegate:delegate];
// Only if JMC is part of the project // Only if JMC is part of the project
if ([[self class] isJMCPresent]) { if ([[self class] isJMCPresent]) {
[[BWHockeyManager sharedHockeyManager] addObserver:self forKeyPath:@"trackerConfig" options:0 context:nil]; [[BWHockeyManager sharedHockeyManager] addObserver:self forKeyPath:@"trackerConfig" options:0 context:nil];

View File

@ -25,6 +25,10 @@
#import "NSString+HockeyAdditions.h" #import "NSString+HockeyAdditions.h"
#ifdef HOCKEYLIB_STATIC_LIBRARY
#import "CNSFixCategoryBug.h"
CNS_FIX_CATEGORY_BUG(NSString_HockeyAdditions)
#endif
@implementation NSString (HockeyAdditions) @implementation NSString (HockeyAdditions)
@ -47,29 +51,28 @@
return result; return result;
} }
- (NSComparisonResult)versionCompare:(NSString *)other - (NSComparisonResult)versionCompare:(NSString *)other {
{ // Extract plain version number from self
// Extract plain version number from self NSString *plainSelf = self;
NSString *plainSelf = self; NSRange letterRange = [plainSelf rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]];
NSRange letterRange = [plainSelf rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]]; if (letterRange.length)
if (letterRange.length) plainSelf = [plainSelf substringToIndex: letterRange.location];
plainSelf = [plainSelf substringToIndex: letterRange.location];
// Extract plain version number from other // Extract plain version number from other
NSString *plainOther = other; NSString *plainOther = other;
letterRange = [plainOther rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]]; letterRange = [plainOther rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]];
if (letterRange.length) if (letterRange.length)
plainOther = [plainOther substringToIndex: letterRange.location]; plainOther = [plainOther substringToIndex: letterRange.location];
// Compare plain versions // Compare plain versions
NSComparisonResult result = [plainSelf compare:plainOther options:NSNumericSearch]; NSComparisonResult result = [plainSelf compare:plainOther options:NSNumericSearch];
// If plain versions are equal, compare full versions // If plain versions are equal, compare full versions
if (result == NSOrderedSame) if (result == NSOrderedSame)
result = [self compare:other options:NSNumericSearch]; result = [self compare:other options:NSNumericSearch];
// Done // Done
return result; return result;
} }
@end @end

View File

@ -232,8 +232,8 @@
- (CGSize)sizeThatFits:(CGSize)size { - (CGSize)sizeThatFits:(CGSize)size {
CGSize constr = (CGSize){.height = self.frame.size.height, .width = PS_MAX_WIDTH}; CGSize constr = (CGSize){.height = self.frame.size.height, .width = PS_MAX_WIDTH};
CGSize newSize = [self.buttonData.label sizeWithFont:self.titleLabel.font constrainedToSize:constr lineBreakMode:UILineBreakModeMiddleTruncation]; CGSize newSize = [self.buttonData.label sizeWithFont:self.titleLabel.font constrainedToSize:constr lineBreakMode:UILineBreakModeMiddleTruncation];
CGFloat newWidth = newSize.width + (PS_PADDING * 2); CGFloat newWidth = newSize.width + (PS_PADDING * 2);
CGFloat newHeight = PS_MIN_HEIGHT > newSize.height ? PS_MIN_HEIGHT : newSize.height; CGFloat newHeight = PS_MIN_HEIGHT > newSize.height ? PS_MIN_HEIGHT : newSize.height;
CGSize sizeThatFits = CGSizeMake(newWidth, newHeight); CGSize sizeThatFits = CGSizeMake(newWidth, newHeight);
@ -250,7 +250,7 @@
rect.size.height = self.frame.size.height; rect.size.height = self.frame.size.height;
aLayer.frame = rect; aLayer.frame = rect;
[aLayer layoutIfNeeded]; [aLayer layoutIfNeeded];
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -52,15 +52,15 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
#pragma mark private #pragma mark private
- (void)addWebView { - (void)addWebView {
if(webViewContent_) { if(webViewContent_) {
CGRect webViewRect = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); CGRect webViewRect = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
if(!webView_) { if(!webView_) {
webView_ = [[[UIWebView alloc] initWithFrame:webViewRect] retain]; webView_ = [[[UIWebView alloc] initWithFrame:webViewRect] retain];
[self addSubview:webView_]; [self addSubview:webView_];
webView_.hidden = YES; webView_.hidden = YES;
webView_.backgroundColor = self.cellBackgroundColor; webView_.backgroundColor = self.cellBackgroundColor;
webView_.opaque = NO; webView_.opaque = NO;
webView_.delegate = self; webView_.delegate = self;
webView_.autoresizingMask = UIViewAutoresizingFlexibleWidth; webView_.autoresizingMask = UIViewAutoresizingFlexibleWidth;
for(UIView* subView in webView_.subviews){ for(UIView* subView in webView_.subviews){
@ -79,32 +79,32 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
} }
} }
} }
else else
webView_.frame = webViewRect; webView_.frame = webViewRect;
NSString *deviceWidth = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? [NSString stringWithFormat:@"%d", CGRectGetWidth(self.bounds)] : @"device-width"; NSString *deviceWidth = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? [NSString stringWithFormat:@"%d", CGRectGetWidth(self.bounds)] : @"device-width";
//BWHockeyLog(@"%@\n%@\%@", PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent); //BWHockeyLog(@"%@\n%@\%@", PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent);
NSString *contentHtml = [NSString stringWithFormat:PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent]; NSString *contentHtml = [NSString stringWithFormat:PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent];
[webView_ loadHTMLString:contentHtml baseURL:nil]; [webView_ loadHTMLString:contentHtml baseURL:nil];
} }
} }
- (void)showWebView { - (void)showWebView {
webView_.hidden = NO; webView_.hidden = NO;
self.textLabel.text = @""; self.textLabel.text = @"";
[self setNeedsDisplay]; [self setNeedsDisplay];
} }
- (void)removeWebView { - (void)removeWebView {
if(webView_) { if(webView_) {
webView_.delegate = nil; webView_.delegate = nil;
[webView_ resignFirstResponder]; [webView_ resignFirstResponder];
[webView_ removeFromSuperview]; [webView_ removeFromSuperview];
[webView_ release]; [webView_ release];
} }
webView_ = nil; webView_ = nil;
[self setNeedsDisplay]; [self setNeedsDisplay];
} }
@ -163,15 +163,15 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
#pragma mark UIWebView #pragma mark UIWebView
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if(navigationType == UIWebViewNavigationTypeOther) if(navigationType == UIWebViewNavigationTypeOther)
return YES; return YES;
return NO; return NO;
} }
- (void)webViewDidFinishLoad:(UIWebView *)webView { - (void)webViewDidFinishLoad:(UIWebView *)webView {
if(webViewContent_) if(webViewContent_)
[self showWebView]; [self showWebView];
CGRect frame = webView_.frame; CGRect frame = webView_.frame;

View File

@ -26,6 +26,11 @@
#import "UIImage+HockeyAdditions.h" #import "UIImage+HockeyAdditions.h"
#import "BWGlobal.h" #import "BWGlobal.h"
#ifdef HOCKEYLIB_STATIC_LIBRARY
#import "CNSFixCategoryBug.h"
CNS_FIX_CATEGORY_BUG(UIImage_HockeyAdditionsPrivate)
#endif
// Private helper methods // Private helper methods
@interface UIImage (HockeyAdditionsPrivate) @interface UIImage (HockeyAdditionsPrivate)
- (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight; - (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight;
@ -82,9 +87,9 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
- (UIImage *)bw_roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize { - (UIImage *)bw_roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize {
// If the image does not have an alpha layer, add one // If the image does not have an alpha layer, add one
UIImage *roundedImage = nil; UIImage *roundedImage = nil;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
BW_IF_IOS4_OR_GREATER( BW_IF_IOS4_OR_GREATER(
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 0.0 for scale means "correct scale for device's main screen". UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 0.0 for scale means "correct scale for device's main screen".
CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale)); // cropping happens here. CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale)); // cropping happens here.
@ -219,20 +224,21 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
image = UIGraphicsGetImageFromCurrentImageContext(); image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); UIGraphicsEndImageContext();
) )
if (!image) { if (!image) {
// Try older method. // Try older method.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, scaledWidth, scaledHeight, 8, (fitSize.width * 4), CGContextRef context = CGBitmapContextCreate(NULL, scaledWidth, scaledHeight, 8, (fitSize.width * 4),
colorSpace, kCGImageAlphaPremultipliedLast); colorSpace, kCGImageAlphaPremultipliedLast);
CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], sourceRect); CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], sourceRect);
CGContextDrawImage(context, destRect, sourceImg); CGContextDrawImage(context, destRect, sourceImg);
CGImageRelease(sourceImg); CGImageRelease(sourceImg);
CGImageRef finalImage = CGBitmapContextCreateImage(context); CGImageRef finalImage = CGBitmapContextCreateImage(context);
CGContextRelease(context); CGContextRelease(context);
CGColorSpaceRelease(colorSpace); CGColorSpaceRelease(colorSpace);
image = [UIImage imageWithCGImage:finalImage]; image = [UIImage imageWithCGImage:finalImage];
CGImageRelease(finalImage); CGImageRelease(finalImage);
} }
return image; return image;
} }
@ -240,37 +246,37 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha, float toAlpha) { CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha, float toAlpha) {
CGImageRef theCGImage = NULL; CGImageRef theCGImage = NULL;
// gradient is always black-white and the mask must be in the gray colorspace // gradient is always black-white and the mask must be in the gray colorspace
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// create the bitmap context // create the bitmap context
CGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh, CGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh,
8, 0, colorSpace, kCGImageAlphaNone); 8, 0, colorSpace, kCGImageAlphaNone);
// define the start and end grayscale values (with the alpha, even though // define the start and end grayscale values (with the alpha, even though
// our bitmap context doesn't support alpha the gradient requires it) // our bitmap context doesn't support alpha the gradient requires it)
CGFloat colors[] = {toAlpha, 1.0, fromAlpha, 1.0}; CGFloat colors[] = {toAlpha, 1.0, fromAlpha, 1.0};
// create the CGGradient and then release the gray color space // create the CGGradient and then release the gray color space
CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2); CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
CGColorSpaceRelease(colorSpace); CGColorSpaceRelease(colorSpace);
// create the start and end points for the gradient vector (straight down) // create the start and end points for the gradient vector (straight down)
CGPoint gradientEndPoint = CGPointZero; CGPoint gradientEndPoint = CGPointZero;
CGPoint gradientStartPoint = CGPointMake(0, pixelsHigh); CGPoint gradientStartPoint = CGPointMake(0, pixelsHigh);
// draw the gradient into the gray bitmap context // draw the gradient into the gray bitmap context
CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint, CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint,
gradientEndPoint, kCGGradientDrawsAfterEndLocation); gradientEndPoint, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(grayScaleGradient); CGGradientRelease(grayScaleGradient);
// convert the context into a CGImageRef and release the context // convert the context into a CGImageRef and release the context
theCGImage = CGBitmapContextCreateImage(gradientBitmapContext); theCGImage = CGBitmapContextCreateImage(gradientBitmapContext);
CGContextRelease(gradientBitmapContext); CGContextRelease(gradientBitmapContext);
// return the imageref containing the gradient // return the imageref containing the gradient
return theCGImage; return theCGImage;
} }
@ -288,29 +294,29 @@ CGContextRef MyOpenBitmapContext(int pixelsWide, int pixelsHigh) {
- (UIImage *)bw_reflectedImageWithHeight:(NSUInteger)height fromAlpha:(float)fromAlpha toAlpha:(float)toAlpha { - (UIImage *)bw_reflectedImageWithHeight:(NSUInteger)height fromAlpha:(float)fromAlpha toAlpha:(float)toAlpha {
if(height == 0) if(height == 0)
return nil; return nil;
// create a bitmap graphics context the size of the image // create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = MyOpenBitmapContext(self.size.width, height); CGContextRef mainViewContentContext = MyOpenBitmapContext(self.size.width, height);
// create a 2 bit CGImage containing a gradient that will be used for masking the // create a 2 bit CGImage containing a gradient that will be used for masking the
// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask // main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient // function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
CGImageRef gradientMaskImage = CreateGradientImage(1, height, fromAlpha, toAlpha); CGImageRef gradientMaskImage = CreateGradientImage(1, height, fromAlpha, toAlpha);
// create an image by masking the bitmap of the mainView content with the gradient view // create an image by masking the bitmap of the mainView content with the gradient view
// then release the pre-masked content bitmap and the gradient bitmap // then release the pre-masked content bitmap and the gradient bitmap
CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, self.size.width, height), gradientMaskImage); CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, self.size.width, height), gradientMaskImage);
CGImageRelease(gradientMaskImage); CGImageRelease(gradientMaskImage);
// draw the image into the bitmap context // draw the image into the bitmap context
CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage); CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage);
// convert the finished reflection image to a UIImage // convert the finished reflection image to a UIImage
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); // returns autoreleased UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); // returns autoreleased
UIGraphicsEndImageContext(); UIGraphicsEndImageContext();
return theImage; return theImage;
} }
- (id)bw_initWithContentsOfResolutionIndependentFile:(NSString *)path { - (id)bw_initWithContentsOfResolutionIndependentFile:(NSString *)path {
@ -337,10 +343,10 @@ CGContextRef MyOpenBitmapContext(int pixelsWide, int pixelsHigh) {
+ (UIImage *)bw_imageNamed:(NSString *)imageName bundle:(NSString *)bundleName { + (UIImage *)bw_imageNamed:(NSString *)imageName bundle:(NSString *)bundleName {
NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *bundlePath = [resourcePath stringByAppendingPathComponent:bundleName]; NSString *bundlePath = [resourcePath stringByAppendingPathComponent:bundleName];
NSString *imagePath = [bundlePath stringByAppendingPathComponent:imageName]; NSString *imagePath = [bundlePath stringByAppendingPathComponent:imageName];
return [UIImage bw_imageWithContentsOfResolutionIndependentFile:imagePath]; return [UIImage bw_imageWithContentsOfResolutionIndependentFile:imagePath];
} }
@end @end

View File

@ -70,7 +70,7 @@ Drag & drop the HockeySDK folder from your project directory to your Xcode proje
1. Open your AppDelegate.m file. 1. Open your AppDelegate.m file.
2. Add the following line at the top of the file below your own #import statements:<pre><code>#import "BWHockeyManager.h"</code></pre> 2. Add the following line at the top of the file below your own #import statements:<pre><code>#import "CNSHockeyManager.h"</code></pre>
3. Search for the method application:didFinishLaunchingWithOptions: 3. Search for the method application:didFinishLaunchingWithOptions:

View File

@ -0,0 +1,372 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1E322DAD148FCE2100077977 /* CNSFixCategoryBug.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E322DAC148FCE2100077977 /* CNSFixCategoryBug.h */; };
E400561E148D79B500EB22B9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; };
E41EB471148D7BF50015DEDC /* BWApp.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB459148D7BF50015DEDC /* BWApp.h */; };
E41EB472148D7BF50015DEDC /* BWApp.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB45A148D7BF50015DEDC /* BWApp.m */; };
E41EB473148D7BF50015DEDC /* BWGlobal.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB45B148D7BF50015DEDC /* BWGlobal.h */; };
E41EB474148D7BF50015DEDC /* BWGlobal.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB45C148D7BF50015DEDC /* BWGlobal.m */; };
E41EB475148D7BF50015DEDC /* BWHockeyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB45D148D7BF50015DEDC /* BWHockeyManager.h */; };
E41EB476148D7BF50015DEDC /* BWHockeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB45E148D7BF50015DEDC /* BWHockeyManager.m */; };
E41EB477148D7BF50015DEDC /* BWHockeySettingsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB45F148D7BF50015DEDC /* BWHockeySettingsViewController.h */; };
E41EB478148D7BF50015DEDC /* BWHockeySettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB460148D7BF50015DEDC /* BWHockeySettingsViewController.m */; };
E41EB479148D7BF50015DEDC /* BWHockeyViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB461148D7BF50015DEDC /* BWHockeyViewController.h */; };
E41EB47A148D7BF50015DEDC /* BWHockeyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB462148D7BF50015DEDC /* BWHockeyViewController.m */; };
E41EB47B148D7BF50015DEDC /* BWQuincyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB463148D7BF50015DEDC /* BWQuincyManager.h */; };
E41EB47C148D7BF50015DEDC /* BWQuincyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB464148D7BF50015DEDC /* BWQuincyManager.m */; };
E41EB47D148D7BF50015DEDC /* CNSHockeyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB465148D7BF50015DEDC /* CNSHockeyManager.h */; };
E41EB47E148D7BF50015DEDC /* CNSHockeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB466148D7BF50015DEDC /* CNSHockeyManager.m */; };
E41EB47F148D7BF50015DEDC /* NSString+HockeyAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB467148D7BF50015DEDC /* NSString+HockeyAdditions.h */; };
E41EB480148D7BF50015DEDC /* NSString+HockeyAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB468148D7BF50015DEDC /* NSString+HockeyAdditions.m */; };
E41EB481148D7BF50015DEDC /* PSAppStoreHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB469148D7BF50015DEDC /* PSAppStoreHeader.h */; };
E41EB482148D7BF50015DEDC /* PSAppStoreHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB46A148D7BF50015DEDC /* PSAppStoreHeader.m */; };
E41EB483148D7BF50015DEDC /* PSStoreButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB46B148D7BF50015DEDC /* PSStoreButton.h */; };
E41EB484148D7BF50015DEDC /* PSStoreButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB46C148D7BF50015DEDC /* PSStoreButton.m */; };
E41EB485148D7BF50015DEDC /* PSWebTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB46D148D7BF50015DEDC /* PSWebTableViewCell.h */; };
E41EB486148D7BF50015DEDC /* PSWebTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB46E148D7BF50015DEDC /* PSWebTableViewCell.m */; };
E41EB487148D7BF50015DEDC /* UIImage+HockeyAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB46F148D7BF50015DEDC /* UIImage+HockeyAdditions.h */; };
E41EB488148D7BF50015DEDC /* UIImage+HockeyAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB470148D7BF50015DEDC /* UIImage+HockeyAdditions.m */; };
E41EB48C148D7C4E0015DEDC /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
1E322DAC148FCE2100077977 /* CNSFixCategoryBug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNSFixCategoryBug.h; sourceTree = "<group>"; };
E400561A148D79B500EB22B9 /* libHockeySDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libHockeySDK.a; sourceTree = BUILT_PRODUCTS_DIR; };
E400561D148D79B500EB22B9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
E400562B148D79B500EB22B9 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
E400562D148D79B500EB22B9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
E4005649148D7A3000EB22B9 /* Hockey.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Hockey.bundle; sourceTree = "<group>"; };
E400564A148D7A3000EB22B9 /* Quincy.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Quincy.bundle; sourceTree = "<group>"; };
E41EB459148D7BF50015DEDC /* BWApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWApp.h; sourceTree = "<group>"; };
E41EB45A148D7BF50015DEDC /* BWApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWApp.m; sourceTree = "<group>"; };
E41EB45B148D7BF50015DEDC /* BWGlobal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWGlobal.h; sourceTree = "<group>"; };
E41EB45C148D7BF50015DEDC /* BWGlobal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWGlobal.m; sourceTree = "<group>"; };
E41EB45D148D7BF50015DEDC /* BWHockeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWHockeyManager.h; sourceTree = "<group>"; };
E41EB45E148D7BF50015DEDC /* BWHockeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWHockeyManager.m; sourceTree = "<group>"; };
E41EB45F148D7BF50015DEDC /* BWHockeySettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWHockeySettingsViewController.h; sourceTree = "<group>"; };
E41EB460148D7BF50015DEDC /* BWHockeySettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWHockeySettingsViewController.m; sourceTree = "<group>"; };
E41EB461148D7BF50015DEDC /* BWHockeyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWHockeyViewController.h; sourceTree = "<group>"; };
E41EB462148D7BF50015DEDC /* BWHockeyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWHockeyViewController.m; sourceTree = "<group>"; };
E41EB463148D7BF50015DEDC /* BWQuincyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BWQuincyManager.h; sourceTree = "<group>"; };
E41EB464148D7BF50015DEDC /* BWQuincyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BWQuincyManager.m; sourceTree = "<group>"; };
E41EB465148D7BF50015DEDC /* CNSHockeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNSHockeyManager.h; sourceTree = "<group>"; };
E41EB466148D7BF50015DEDC /* CNSHockeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNSHockeyManager.m; sourceTree = "<group>"; };
E41EB467148D7BF50015DEDC /* NSString+HockeyAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+HockeyAdditions.h"; sourceTree = "<group>"; };
E41EB468148D7BF50015DEDC /* NSString+HockeyAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+HockeyAdditions.m"; sourceTree = "<group>"; };
E41EB469148D7BF50015DEDC /* PSAppStoreHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSAppStoreHeader.h; sourceTree = "<group>"; };
E41EB46A148D7BF50015DEDC /* PSAppStoreHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSAppStoreHeader.m; sourceTree = "<group>"; };
E41EB46B148D7BF50015DEDC /* PSStoreButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSStoreButton.h; sourceTree = "<group>"; };
E41EB46C148D7BF50015DEDC /* PSStoreButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSStoreButton.m; sourceTree = "<group>"; };
E41EB46D148D7BF50015DEDC /* PSWebTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSWebTableViewCell.h; sourceTree = "<group>"; };
E41EB46E148D7BF50015DEDC /* PSWebTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSWebTableViewCell.m; sourceTree = "<group>"; };
E41EB46F148D7BF50015DEDC /* UIImage+HockeyAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+HockeyAdditions.h"; sourceTree = "<group>"; };
E41EB470148D7BF50015DEDC /* UIImage+HockeyAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+HockeyAdditions.m"; sourceTree = "<group>"; };
E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CrashReporter.framework; path = ../Vendor/CrashReporter.framework; sourceTree = "<group>"; };
E4E7335A148D7A5A00763A39 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = LICENSE.txt; path = ../LICENSE.txt; sourceTree = "<group>"; };
E4E7335B148D7A5A00763A39 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; name = README.md; path = ../README.md; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E4005617148D79B500EB22B9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E400561E148D79B500EB22B9 /* Foundation.framework in Frameworks */,
E41EB48C148D7C4E0015DEDC /* CrashReporter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E400560F148D79B500EB22B9 = {
isa = PBXGroup;
children = (
E41EB489148D7BF90015DEDC /* HockeySDK */,
E400561C148D79B500EB22B9 /* Frameworks */,
E4005648148D7A3000EB22B9 /* Resources */,
E400561B148D79B500EB22B9 /* Products */,
E4E7335A148D7A5A00763A39 /* LICENSE.txt */,
E4E7335B148D7A5A00763A39 /* README.md */,
);
sourceTree = "<group>";
};
E400561B148D79B500EB22B9 /* Products */ = {
isa = PBXGroup;
children = (
E400561A148D79B500EB22B9 /* libHockeySDK.a */,
);
name = Products;
sourceTree = "<group>";
};
E400561C148D79B500EB22B9 /* Frameworks */ = {
isa = PBXGroup;
children = (
E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */,
E400561D148D79B500EB22B9 /* Foundation.framework */,
E400562B148D79B500EB22B9 /* SenTestingKit.framework */,
E400562D148D79B500EB22B9 /* UIKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
E4005648148D7A3000EB22B9 /* Resources */ = {
isa = PBXGroup;
children = (
E4005649148D7A3000EB22B9 /* Hockey.bundle */,
E400564A148D7A3000EB22B9 /* Quincy.bundle */,
);
name = Resources;
path = ../Resources;
sourceTree = "<group>";
};
E41EB458148D7BF50015DEDC /* Classes */ = {
isa = PBXGroup;
children = (
E41EB48A148D7C150015DEDC /* Helper */,
E41EB459148D7BF50015DEDC /* BWApp.h */,
E41EB45A148D7BF50015DEDC /* BWApp.m */,
E41EB45B148D7BF50015DEDC /* BWGlobal.h */,
E41EB45C148D7BF50015DEDC /* BWGlobal.m */,
E41EB45D148D7BF50015DEDC /* BWHockeyManager.h */,
E41EB45E148D7BF50015DEDC /* BWHockeyManager.m */,
E41EB45F148D7BF50015DEDC /* BWHockeySettingsViewController.h */,
E41EB460148D7BF50015DEDC /* BWHockeySettingsViewController.m */,
E41EB461148D7BF50015DEDC /* BWHockeyViewController.h */,
E41EB462148D7BF50015DEDC /* BWHockeyViewController.m */,
E41EB463148D7BF50015DEDC /* BWQuincyManager.h */,
E41EB464148D7BF50015DEDC /* BWQuincyManager.m */,
E41EB465148D7BF50015DEDC /* CNSHockeyManager.h */,
E41EB466148D7BF50015DEDC /* CNSHockeyManager.m */,
);
name = Classes;
path = ../Classes;
sourceTree = "<group>";
};
E41EB489148D7BF90015DEDC /* HockeySDK */ = {
isa = PBXGroup;
children = (
E41EB458148D7BF50015DEDC /* Classes */,
);
name = HockeySDK;
sourceTree = "<group>";
};
E41EB48A148D7C150015DEDC /* Helper */ = {
isa = PBXGroup;
children = (
E41EB467148D7BF50015DEDC /* NSString+HockeyAdditions.h */,
E41EB468148D7BF50015DEDC /* NSString+HockeyAdditions.m */,
E41EB469148D7BF50015DEDC /* PSAppStoreHeader.h */,
E41EB46A148D7BF50015DEDC /* PSAppStoreHeader.m */,
E41EB46B148D7BF50015DEDC /* PSStoreButton.h */,
E41EB46C148D7BF50015DEDC /* PSStoreButton.m */,
E41EB46D148D7BF50015DEDC /* PSWebTableViewCell.h */,
E41EB46E148D7BF50015DEDC /* PSWebTableViewCell.m */,
E41EB46F148D7BF50015DEDC /* UIImage+HockeyAdditions.h */,
E41EB470148D7BF50015DEDC /* UIImage+HockeyAdditions.m */,
1E322DAC148FCE2100077977 /* CNSFixCategoryBug.h */,
);
name = Helper;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
E4005618148D79B500EB22B9 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
E41EB471148D7BF50015DEDC /* BWApp.h in Headers */,
E41EB473148D7BF50015DEDC /* BWGlobal.h in Headers */,
E41EB475148D7BF50015DEDC /* BWHockeyManager.h in Headers */,
E41EB477148D7BF50015DEDC /* BWHockeySettingsViewController.h in Headers */,
E41EB479148D7BF50015DEDC /* BWHockeyViewController.h in Headers */,
E41EB47B148D7BF50015DEDC /* BWQuincyManager.h in Headers */,
E41EB47D148D7BF50015DEDC /* CNSHockeyManager.h in Headers */,
E41EB47F148D7BF50015DEDC /* NSString+HockeyAdditions.h in Headers */,
E41EB481148D7BF50015DEDC /* PSAppStoreHeader.h in Headers */,
E41EB483148D7BF50015DEDC /* PSStoreButton.h in Headers */,
E41EB485148D7BF50015DEDC /* PSWebTableViewCell.h in Headers */,
E41EB487148D7BF50015DEDC /* UIImage+HockeyAdditions.h in Headers */,
1E322DAD148FCE2100077977 /* CNSFixCategoryBug.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
E4005619148D79B500EB22B9 /* HockeySDK */ = {
isa = PBXNativeTarget;
buildConfigurationList = E400563E148D79B500EB22B9 /* Build configuration list for PBXNativeTarget "HockeySDK" */;
buildPhases = (
E4005616148D79B500EB22B9 /* Sources */,
E4005617148D79B500EB22B9 /* Frameworks */,
E4005618148D79B500EB22B9 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = HockeySDK;
productName = HockeySDK;
productReference = E400561A148D79B500EB22B9 /* libHockeySDK.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E4005611148D79B500EB22B9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
};
buildConfigurationList = E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = E400560F148D79B500EB22B9;
productRefGroup = E400561B148D79B500EB22B9 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E4005619148D79B500EB22B9 /* HockeySDK */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
E4005616148D79B500EB22B9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E41EB472148D7BF50015DEDC /* BWApp.m in Sources */,
E41EB474148D7BF50015DEDC /* BWGlobal.m in Sources */,
E41EB476148D7BF50015DEDC /* BWHockeyManager.m in Sources */,
E41EB478148D7BF50015DEDC /* BWHockeySettingsViewController.m in Sources */,
E41EB47A148D7BF50015DEDC /* BWHockeyViewController.m in Sources */,
E41EB47C148D7BF50015DEDC /* BWQuincyManager.m in Sources */,
E41EB47E148D7BF50015DEDC /* CNSHockeyManager.m in Sources */,
E41EB480148D7BF50015DEDC /* NSString+HockeyAdditions.m in Sources */,
E41EB482148D7BF50015DEDC /* PSAppStoreHeader.m in Sources */,
E41EB484148D7BF50015DEDC /* PSStoreButton.m in Sources */,
E41EB486148D7BF50015DEDC /* PSWebTableViewCell.m in Sources */,
E41EB488148D7BF50015DEDC /* UIImage+HockeyAdditions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
E400563C148D79B500EB22B9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv7,
armv6,
);
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
HOCKEYLIB_STATIC_LIBRARY,
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = "";
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
OTHER_CFLAGS = "";
SDKROOT = iphoneos;
};
name = Debug;
};
E400563D148D79B500EB22B9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
armv7,
armv6,
);
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = HOCKEYLIB_STATIC_LIBRARY;
GCC_VERSION = "";
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
OTHER_CFLAGS = "";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
E400563F148D79B500EB22B9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DSTROOT = /tmp/HockeySDK.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../Vendor\"",
);
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
E4005640148D79B500EB22B9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DSTROOT = /tmp/HockeySDK.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../Vendor\"",
);
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E400563C148D79B500EB22B9 /* Debug */,
E400563D148D79B500EB22B9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E400563E148D79B500EB22B9 /* Build configuration list for PBXNativeTarget "HockeySDK" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E400563F148D79B500EB22B9 /* Debug */,
E4005640148D79B500EB22B9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E4005611148D79B500EB22B9 /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:HockeySDK.xcodeproj">
</FileRef>
</Workspace>