mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-16 10:30:08 +00:00
Merge branch 'refs/heads/feature/CrashReporting' into feature/CrashDetails
Conflicts: Classes/BITCrashManager.h
This commit is contained in:
commit
c4e7754a8b
0
Classes/BITAttributedLabel.h
Executable file → Normal file
0
Classes/BITAttributedLabel.h
Executable file → Normal file
0
Classes/BITAttributedLabel.m
Executable file → Normal file
0
Classes/BITAttributedLabel.m
Executable file → Normal file
@ -108,19 +108,19 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
|
||||
// make sure this is called after startManager so all modules are fully setup
|
||||
if (!_isSetup) {
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(authenticateInstallation) object:nil];
|
||||
[self performSelector:@selector(authenticateInstallation) withObject:nil afterDelay:0.1];
|
||||
} else {
|
||||
switch ([[UIApplication sharedApplication] applicationState]) {
|
||||
case UIApplicationStateActive:
|
||||
[self authenticate];
|
||||
break;
|
||||
case UIApplicationStateBackground:
|
||||
case UIApplicationStateInactive:
|
||||
// do nothing, wait for active state
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch ([[UIApplication sharedApplication] applicationState]) {
|
||||
case UIApplicationStateActive:
|
||||
[self authenticate];
|
||||
break;
|
||||
case UIApplicationStateBackground:
|
||||
case UIApplicationStateInactive:
|
||||
// do nothing, wait for active state
|
||||
break;
|
||||
}
|
||||
|
||||
[self registerObservers];
|
||||
}
|
||||
|
||||
@ -156,6 +156,10 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
}
|
||||
|
||||
- (void)alertOnFailureStoringTokenInKeychain {
|
||||
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerStorageError")
|
||||
delegate:self
|
||||
@ -607,7 +611,6 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
case BITAuthenticatorIdentificationTypeHockeyAppEmail:
|
||||
case BITAuthenticatorIdentificationTypeAnonymous:
|
||||
case BITAuthenticatorIdentificationTypeHockeyAppUser:
|
||||
NSAssert(NO, @"Should only be called for Device and WebAuth identificationType");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
66
Classes/BITCrashAttachment.h
Normal file
66
Classes/BITCrashAttachment.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Provides support to add binary attachments to crash reports
|
||||
*
|
||||
* This is used by `[BITCrashManagerDelegate attachmentForCrashManager:]`
|
||||
*/
|
||||
@interface BITCrashAttachment : NSObject<NSCoding>
|
||||
|
||||
/**
|
||||
* The filename the attachment should get
|
||||
*/
|
||||
@property (nonatomic, readonly, strong) NSString *filename;
|
||||
|
||||
/**
|
||||
* The attachment data as NSData object
|
||||
*/
|
||||
@property (nonatomic, readonly, strong) NSData *attachmentData;
|
||||
|
||||
/**
|
||||
* The content type of your data as MIME type
|
||||
*/
|
||||
@property (nonatomic, readonly, strong) NSString *contentType;
|
||||
|
||||
/**
|
||||
* Create an BITCrashAttachment instance with a given filename and NSData object
|
||||
*
|
||||
* @param filename The filename the attachment should get
|
||||
* @param attachmentData The attachment data as NSData
|
||||
* @param contentType The content type of your data as MIME type
|
||||
*
|
||||
* @return An instsance of BITCrashAttachment
|
||||
*/
|
||||
- (instancetype)initWithFilename:(NSString *)filename
|
||||
attachmentData:(NSData *)attachmentData
|
||||
contentType:(NSString *)contentType;
|
||||
|
||||
@end
|
64
Classes/BITCrashAttachment.m
Normal file
64
Classes/BITCrashAttachment.m
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "BITCrashAttachment.h"
|
||||
|
||||
@implementation BITCrashAttachment
|
||||
|
||||
- (instancetype)initWithFilename:(NSString *)filename
|
||||
attachmentData:(NSData *)attachmentData
|
||||
contentType:(NSString *)contentType
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_filename = filename;
|
||||
_attachmentData = attachmentData;
|
||||
_contentType = contentType;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - NSCoder
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder {
|
||||
[encoder encodeObject:self.filename forKey:@"filename"];
|
||||
[encoder encodeObject:self.attachmentData forKey:@"data"];
|
||||
[encoder encodeObject:self.contentType forKey:@"contentType"];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
if ((self = [super init])) {
|
||||
_filename = [decoder decodeObjectForKey:@"filename"];
|
||||
_attachmentData = [decoder decodeObjectForKey:@"data"];
|
||||
_contentType = [decoder decodeObjectForKey:@"contentType"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
@ -34,6 +34,11 @@
|
||||
|
||||
@class BITCrashDetails;
|
||||
|
||||
/**
|
||||
* Custom block that handles the alert that prompts the user whether he wants to send crash reports
|
||||
*/
|
||||
typedef void(^CustomAlertViewHandler)();
|
||||
|
||||
|
||||
/**
|
||||
* Crash Manager status
|
||||
@ -54,6 +59,54 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Prototype of a callback function used to execute additional user code. Called upon completion of crash
|
||||
* handling, after the crash report has been written to disk.
|
||||
*
|
||||
* @param context The API client's supplied context value.
|
||||
*
|
||||
* @see `BITCrashManagerCallbacks`
|
||||
* @see `[BITCrashManager setCrashCallbacks:]`
|
||||
*/
|
||||
typedef void (*BITCrashManagerPostCrashSignalCallback)(void *context);
|
||||
|
||||
/**
|
||||
* This structure contains callbacks supported by `BITCrashManager` to allow the host application to perform
|
||||
* additional tasks prior to program termination after a crash has occured.
|
||||
*
|
||||
* @see `BITCrashManagerPostCrashSignalCallback`
|
||||
* @see `[BITCrashManager setCrashCallbacks:]`
|
||||
*/
|
||||
typedef struct BITCrashManagerCallbacks {
|
||||
/** An arbitrary user-supplied context value. This value may be NULL. */
|
||||
void *context;
|
||||
|
||||
/**
|
||||
* The callback used to report caught signal information.
|
||||
*/
|
||||
BITCrashManagerPostCrashSignalCallback handleSignal;
|
||||
} BITCrashManagerCallbacks;
|
||||
|
||||
/**
|
||||
* Crash Manager alert user input
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, BITCrashManagerUserInput) {
|
||||
/**
|
||||
* User chose not to send the crash report
|
||||
*/
|
||||
BITCrashManagerUserInputDontSend = 0,
|
||||
/**
|
||||
* User wants the crash report to be sent
|
||||
*/
|
||||
BITCrashManagerUserInputSend = 1,
|
||||
/**
|
||||
* User chose to always send crash reports
|
||||
*/
|
||||
BITCrashManagerUserInputAlwaysSend = 2
|
||||
|
||||
};
|
||||
|
||||
|
||||
@protocol BITCrashManagerDelegate;
|
||||
|
||||
/**
|
||||
@ -229,15 +282,18 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
|
||||
*
|
||||
* _Async-Safe Functions_
|
||||
*
|
||||
* A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the CERT programming guide - SIG30-C, see https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
|
||||
* A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the [CERT programming guide - SIG30-C](https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers).
|
||||
*
|
||||
* Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal handler.
|
||||
*
|
||||
* Documentation taken from PLCrashReporter: https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html
|
||||
*
|
||||
* @see `BITCrashManagerPostCrashSignalCallback`
|
||||
* @see `BITCrashManagerCallbacks`
|
||||
*
|
||||
* @param callbacks A pointer to an initialized PLCrashReporterCallback structure, see https://www.plcrashreporter.org/documentation/api/v1.2-rc2/struct_p_l_crash_reporter_callbacks.html
|
||||
*/
|
||||
- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks;
|
||||
- (void)setCrashCallbacks: (BITCrashManagerCallbacks *) callbacks;
|
||||
|
||||
|
||||
/**
|
||||
@ -272,6 +328,26 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL didCrashInLastSession;
|
||||
|
||||
/**
|
||||
Provides an interface to handle user input from a custom alert
|
||||
|
||||
@param userInput On this input depends, whether crash reports are sent, always sent or not sent and deleted.
|
||||
@param userProvidedCrashDescription The content of this optional string will be attached to the crash report as the description and allows to ask the user for e.g. additional comments or info
|
||||
|
||||
@return Returns YES if the input is a valid option and successfully triggered further processing of the crash report
|
||||
@see BITCrashManagerUserInput
|
||||
*/
|
||||
- (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedCrashDescription:(NSString*)userProvidedCrashDescription;
|
||||
|
||||
/**
|
||||
Lets you set a custom block which handles showing a custom UI and asking the user
|
||||
whether he wants to send the crash report.
|
||||
|
||||
@param alertViewHandler A block that is responsible for loading, presenting and and dismissing your custom user interface which prompts the user if he wants to send crash reports. The block is also responsible for triggering further processing of the crash reports.
|
||||
|
||||
@warning Block needs to call the `handleUserInput:withUserProvidedCrashDescription` method!
|
||||
*/
|
||||
- (void) setAlertViewHandler:(CustomAlertViewHandler)alertViewHandler;
|
||||
|
||||
/**
|
||||
Indicates if the app was killed while being in foreground from the iOS
|
||||
|
@ -32,12 +32,16 @@
|
||||
|
||||
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
|
||||
|
||||
#import <CrashReporter/CrashReporter.h>
|
||||
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "HockeySDKPrivate.h"
|
||||
#import "BITHockeyHelper.h"
|
||||
#import "BITHockeyAppClient.h"
|
||||
|
||||
#import "BITCrashAttachment.h"
|
||||
#import "BITHockeyBaseManagerPrivate.h"
|
||||
#import "BITCrashManagerPrivate.h"
|
||||
#import "BITCrashReportTextFormatter.h"
|
||||
@ -52,6 +56,11 @@
|
||||
#define kBITCrashMetaUserEmail @"BITCrashMetaUserEmail"
|
||||
#define kBITCrashMetaUserID @"BITCrashMetaUserID"
|
||||
#define kBITCrashMetaApplicationLog @"BITCrashMetaApplicationLog"
|
||||
#define kBITCrashMetaAttachment @"BITCrashMetaAttachment"
|
||||
|
||||
// internal keys
|
||||
NSString *const KBITAttachmentDictIndex = @"index";
|
||||
NSString *const KBITAttachmentDictAttachment = @"attachment";
|
||||
|
||||
NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
|
||||
@ -69,9 +78,28 @@ NSString *const kBITFakeCrashDeviceModel = @"BITFakeCrashDeviceModel";
|
||||
NSString *const kBITFakeCrashAppBinaryUUID = @"BITFakeCrashAppBinaryUUID";
|
||||
NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
|
||||
|
||||
static BITCrashManagerCallbacks bitCrashCallbacks = {
|
||||
.context = NULL,
|
||||
.handleSignal = NULL
|
||||
};
|
||||
|
||||
// proxy implementation for PLCrashReporter to keep our interface stable while this can change
|
||||
static void plcr_post_crash_callback (siginfo_t *info, ucontext_t *uap, void *context) {
|
||||
if (bitCrashCallbacks.handleSignal != NULL)
|
||||
bitCrashCallbacks.handleSignal(context);
|
||||
}
|
||||
|
||||
static PLCrashReporterCallbacks plCrashCallbacks = {
|
||||
.version = 0,
|
||||
.context = NULL,
|
||||
.handleSignal = plcr_post_crash_callback
|
||||
};
|
||||
|
||||
|
||||
@interface BITCrashManager ()
|
||||
|
||||
@property (nonatomic, strong) NSFileManager *fileManager;
|
||||
@property (nonatomic, copy, setter = setAlertViewHandler:) CustomAlertViewHandler alertViewHandler;
|
||||
|
||||
@end
|
||||
|
||||
@ -80,10 +108,11 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
|
||||
NSMutableArray *_crashFiles;
|
||||
NSString *_crashesDir;
|
||||
NSString *_lastCrashFilename;
|
||||
NSString *_settingsFile;
|
||||
NSString *_analyzerInProgressFile;
|
||||
NSFileManager *_fileManager;
|
||||
|
||||
|
||||
PLCrashReporterCallbacks *_crashCallBacks;
|
||||
|
||||
BOOL _crashIdenticalCurrentVersion;
|
||||
@ -127,6 +156,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
_didLogLowMemoryWarning = NO;
|
||||
|
||||
_approvedCrashReports = [[NSMutableDictionary alloc] init];
|
||||
_alertViewHandler = nil;
|
||||
|
||||
_fileManager = [[NSFileManager alloc] init];
|
||||
_crashFiles = [[NSMutableArray alloc] init];
|
||||
@ -187,9 +217,9 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
NSString *errorString = nil;
|
||||
|
||||
NSMutableDictionary *rootObj = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||
if (_approvedCrashReports && [_approvedCrashReports count] > 0)
|
||||
if (_approvedCrashReports && [_approvedCrashReports count] > 0) {
|
||||
[rootObj setObject:_approvedCrashReports forKey:kBITCrashApprovedReports];
|
||||
|
||||
}
|
||||
NSData *plist = [NSPropertyListSerialization dataFromPropertyList:(id)rootObj
|
||||
format:NSPropertyListBinaryFormat_v1_0
|
||||
errorDescription:&errorString];
|
||||
@ -234,13 +264,11 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
NSError *error = NULL;
|
||||
|
||||
for (NSUInteger i=0; i < [_crashFiles count]; i++) {
|
||||
[_fileManager removeItemAtPath:[_crashFiles objectAtIndex:i] error:&error];
|
||||
[_fileManager removeItemAtPath:[[_crashFiles objectAtIndex:i] stringByAppendingString:@".meta"] error:&error];
|
||||
|
||||
NSString *filename = [_crashFiles objectAtIndex:i];
|
||||
NSString *cacheFilename = [[_crashFiles objectAtIndex:i] lastPathComponent];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
|
||||
|
||||
[self cleanFilesAndKeychainWithFileName:filename CacheFilename:cacheFilename Error:error];
|
||||
|
||||
}
|
||||
[_crashFiles removeAllObjects];
|
||||
[_approvedCrashReports removeAllObjects];
|
||||
@ -248,9 +276,74 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
[self saveSettings];
|
||||
}
|
||||
|
||||
- (void)cleanFilesAndKeychainWithFileName:(NSString *)filename CacheFilename:(NSString *)cacheFilename Error:(NSError *)error{
|
||||
[_fileManager removeItemAtPath:filename error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.data", filename] error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", filename] error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.desc", filename] error:&error];
|
||||
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
|
||||
}
|
||||
|
||||
- (void)persistAttachment:(BITCrashAttachment *)attachment withFilename:(NSString *)filename {
|
||||
NSString *attachmentFilename = [filename stringByAppendingString:@".data"];
|
||||
NSMutableData *data = [[NSMutableData alloc] init];
|
||||
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
|
||||
|
||||
[archiver encodeObject:attachment forKey:kBITCrashMetaAttachment];
|
||||
|
||||
[archiver finishEncoding];
|
||||
|
||||
[data writeToFile:attachmentFilename atomically:YES];
|
||||
}
|
||||
|
||||
- (void)persistUserProvidedCrashDescription:(NSString *)userProvidedCrashDescription {
|
||||
if (userProvidedCrashDescription && [userProvidedCrashDescription length] > 0) {
|
||||
NSError *error;
|
||||
[userProvidedCrashDescription writeToFile:[NSString stringWithFormat:@"%@.desc", [_crashesDir stringByAppendingPathComponent: _lastCrashFilename]] atomically:YES encoding:NSUTF8StringEncoding error:&error];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the attachment data from the stored file
|
||||
*
|
||||
* @param filename The crash report id
|
||||
*
|
||||
* @return an BITCrashAttachment instance or nil
|
||||
*/
|
||||
- (BITCrashAttachment *)attachmentForCrashReport:(NSString *)filename {
|
||||
NSString *attachmentFilename = [filename stringByAppendingString:@".data"];
|
||||
|
||||
if (![_fileManager fileExistsAtPath:attachmentFilename])
|
||||
return nil;
|
||||
|
||||
|
||||
NSData *codedData = [[NSData alloc] initWithContentsOfFile:attachmentFilename];
|
||||
if (!codedData)
|
||||
return nil;
|
||||
|
||||
NSKeyedUnarchiver *unarchiver = nil;
|
||||
|
||||
@try {
|
||||
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([unarchiver containsValueForKey:kBITCrashMetaAttachment]) {
|
||||
BITCrashAttachment *attachment = [unarchiver decodeObjectForKey:kBITCrashMetaAttachment];
|
||||
return attachment;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all app sepcific UUIDs from the crash reports
|
||||
*
|
||||
*
|
||||
* This allows us to send the UUIDs in the XML construct to the server, so the server does not need to parse the crash report for this data.
|
||||
* The app specific UUIDs help to identify which dSYMs are needed to symbolicate this crash report.
|
||||
*
|
||||
@ -474,7 +567,8 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
// if we have an identification from BITAuthenticator, use this as a default.
|
||||
if ((
|
||||
self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppEmail ||
|
||||
self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppUser
|
||||
self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppUser ||
|
||||
self.installationIdentificationType == BITAuthenticatorIdentificationTypeWebAuth
|
||||
) &&
|
||||
self.installationIdentification) {
|
||||
useremail = self.installationIdentification;
|
||||
@ -494,12 +588,34 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
return useremail;
|
||||
}
|
||||
|
||||
- (NSString *)getCrashesDir {
|
||||
return _crashesDir;
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
|
||||
- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks {
|
||||
_crashCallBacks = callbacks;
|
||||
/**
|
||||
* Set the callback for PLCrashReporter
|
||||
*
|
||||
* @param callbacks BITCrashManagerCallbacks instance
|
||||
*/
|
||||
- (void)setCrashCallbacks: (BITCrashManagerCallbacks *) callbacks {
|
||||
if (!callbacks) return;
|
||||
|
||||
// set our proxy callback struct
|
||||
bitCrashCallbacks.context = callbacks->context;
|
||||
bitCrashCallbacks.handleSignal = callbacks->handleSignal;
|
||||
|
||||
// set the PLCrashReporterCallbacks struct
|
||||
plCrashCallbacks.context = callbacks->context;
|
||||
|
||||
_crashCallBacks = &plCrashCallbacks;
|
||||
}
|
||||
|
||||
|
||||
- (void)setAlertViewHandler:(CustomAlertViewHandler)alertViewHandler{
|
||||
_alertViewHandler = alertViewHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -567,6 +683,14 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
}
|
||||
[metaDict setObject:applicationLog forKey:kBITCrashMetaApplicationLog];
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(attachmentForCrashManager:)]) {
|
||||
BITCrashAttachment *attachment = [self.delegate attachmentForCrashManager:self];
|
||||
|
||||
if (attachment) {
|
||||
[self persistAttachment:attachment withFilename:[_crashesDir stringByAppendingPathComponent: filename]];
|
||||
}
|
||||
}
|
||||
|
||||
NSData *plist = [NSPropertyListSerialization dataFromPropertyList:(id)metaDict
|
||||
format:NSPropertyListBinaryFormat_v1_0
|
||||
errorDescription:&errorString];
|
||||
@ -577,6 +701,41 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedCrashDescription:(NSString *)userProvidedCrashDescription{
|
||||
switch (userInput) {
|
||||
case BITCrashManagerUserInputDontSend:
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) {
|
||||
[self.delegate crashManagerWillCancelSendingCrashReport:self];
|
||||
}
|
||||
|
||||
[self cleanCrashReports];
|
||||
return YES;
|
||||
|
||||
case BITCrashManagerUserInputSend:
|
||||
[self persistUserProvidedCrashDescription:userProvidedCrashDescription];
|
||||
|
||||
[self sendCrashReports];
|
||||
return YES;
|
||||
|
||||
case BITCrashManagerUserInputAlwaysSend:
|
||||
_crashManagerStatus = BITCrashManagerStatusAutoSend;
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:_crashManagerStatus forKey:kBITCrashManagerStatus];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillSendCrashReportsAlways:)]) {
|
||||
[self.delegate crashManagerWillSendCrashReportsAlways:self];
|
||||
}
|
||||
|
||||
[self persistUserProvidedCrashDescription:userProvidedCrashDescription];
|
||||
|
||||
[self sendCrashReports];
|
||||
return YES;
|
||||
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - PLCrashReporter
|
||||
|
||||
/**
|
||||
@ -602,6 +761,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
NSData *crashData = [[NSData alloc] initWithData:[self.plCrashReporter loadPendingCrashReportDataAndReturnError: &error]];
|
||||
|
||||
NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
|
||||
_lastCrashFilename = cacheFilename;
|
||||
|
||||
if (crashData == nil) {
|
||||
BITHockeyLog(@"ERROR: Could not load crash report: %@", error);
|
||||
@ -676,7 +836,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
/**
|
||||
* Check if there are any new crash reports that are not yet processed
|
||||
*
|
||||
* @return `YES` if ther eis at least one new crash report found, `NO` otherwise
|
||||
* @return `YES` if there is at least one new crash report found, `NO` otherwise
|
||||
*/
|
||||
- (BOOL)hasPendingCrashReport {
|
||||
if (_crashManagerStatus == BITCrashManagerStatusDisabled) return NO;
|
||||
@ -693,7 +853,9 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
![file hasSuffix:@".DS_Store"] &&
|
||||
![file hasSuffix:@".analyzer"] &&
|
||||
![file hasSuffix:@".plist"] &&
|
||||
![file hasSuffix:@".meta"]) {
|
||||
![file hasSuffix:@".data"] &&
|
||||
![file hasSuffix:@".meta"] &&
|
||||
![file hasSuffix:@".desc"]) {
|
||||
[_crashFiles addObject:[_crashesDir stringByAppendingPathComponent: file]];
|
||||
}
|
||||
}
|
||||
@ -771,17 +933,21 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
alertDescription = [NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundDescription"), appName];
|
||||
}
|
||||
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundTitle"), appName]
|
||||
message:alertDescription
|
||||
delegate:self
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"CrashDontSendReport")
|
||||
otherButtonTitles:BITHockeyLocalizedString(@"CrashSendReport"), nil];
|
||||
|
||||
if (self.shouldShowAlwaysButton) {
|
||||
[alertView addButtonWithTitle:BITHockeyLocalizedString(@"CrashSendReportAlways")];
|
||||
if (_alertViewHandler) {
|
||||
_alertViewHandler();
|
||||
} else {
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundTitle"), appName]
|
||||
message:alertDescription
|
||||
delegate:self
|
||||
cancelButtonTitle:BITHockeyLocalizedString(@"CrashDontSendReport")
|
||||
otherButtonTitles:BITHockeyLocalizedString(@"CrashSendReport"), nil];
|
||||
|
||||
if (self.shouldShowAlwaysButton) {
|
||||
[alertView addButtonWithTitle:BITHockeyLocalizedString(@"CrashSendReportAlways")];
|
||||
}
|
||||
|
||||
[alertView show];
|
||||
}
|
||||
|
||||
[alertView show];
|
||||
} else {
|
||||
[self sendCrashReports];
|
||||
}
|
||||
@ -1004,6 +1170,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
NSError *error = NULL;
|
||||
|
||||
NSMutableString *crashes = nil;
|
||||
NSMutableArray *attachments = [NSMutableArray array];
|
||||
_crashIdenticalCurrentVersion = NO;
|
||||
|
||||
for (NSUInteger i=0; i < [_crashFiles count]; i++) {
|
||||
@ -1053,12 +1220,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
if (report == nil && crashLogString == nil) {
|
||||
BITHockeyLog(@"WARNING: Could not parse crash report");
|
||||
// we cannot do anything with this report, so delete it
|
||||
[_fileManager removeItemAtPath:filename error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", metaFilename] error:&error];
|
||||
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
|
||||
[self cleanFilesAndKeychainWithFileName:filename CacheFilename:cacheFilename Error:error];
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1102,12 +1264,24 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
useremail = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]] ?: @"";
|
||||
userid = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]] ?: @"";
|
||||
applicationLog = [metaDict objectForKey:kBITCrashMetaApplicationLog] ?: @"";
|
||||
description = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%@.desc", [_crashesDir stringByAppendingPathComponent: cacheFilename]] encoding:NSUTF8StringEncoding error:&error];
|
||||
|
||||
BITCrashAttachment *attachment = [self attachmentForCrashReport:filename];
|
||||
if (attachment) {
|
||||
NSDictionary *attachmentDict = @{KBITAttachmentDictIndex: @(i),
|
||||
KBITAttachmentDictAttachment: attachment};
|
||||
[attachments addObject:attachmentDict];
|
||||
}
|
||||
} else {
|
||||
BITHockeyLog(@"ERROR: Reading crash meta data. %@", error);
|
||||
}
|
||||
|
||||
if ([applicationLog length] > 0) {
|
||||
description = [NSString stringWithFormat:@"%@", applicationLog];
|
||||
if ([description length] > 0) {
|
||||
description = [NSString stringWithFormat:@"%@\n\nLog:\n%@", description, applicationLog];
|
||||
} else {
|
||||
description = [NSString stringWithFormat:@"Log:\n%@", applicationLog];
|
||||
}
|
||||
}
|
||||
|
||||
[crashes appendFormat:@"<crash><applicationname>%s</applicationname><uuids>%@</uuids><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><uuid>%@</uuid><log><![CDATA[%@]]></log><userid>%@</userid><username>%@</username><contact>%@</contact><installstring>%@</installstring><description><![CDATA[%@]]></description></crash>",
|
||||
@ -1131,12 +1305,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
[_approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:filename];
|
||||
} else {
|
||||
// we cannot do anything with this report, so delete it
|
||||
[_fileManager removeItemAtPath:filename error:&error];
|
||||
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", filename] error:&error];
|
||||
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
|
||||
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
|
||||
[self cleanFilesAndKeychainWithFileName:filename CacheFilename:cacheFilename Error:error];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,7 +1313,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
|
||||
if (crashes != nil) {
|
||||
BITHockeyLog(@"INFO: Sending crash reports:\n%@", crashes);
|
||||
[self postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes]];
|
||||
[self postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes] attachments:attachments];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1154,35 +1323,20 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
|
||||
switch (buttonIndex) {
|
||||
case 0:
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) {
|
||||
[self.delegate crashManagerWillCancelSendingCrashReport:self];
|
||||
}
|
||||
|
||||
_sendingInProgress = NO;
|
||||
[self cleanCrashReports];
|
||||
[self handleUserInput:BITCrashManagerUserInputDontSend withUserProvidedCrashDescription:nil];
|
||||
break;
|
||||
case 1:
|
||||
[self sendCrashReports];
|
||||
[self handleUserInput:BITCrashManagerUserInputSend withUserProvidedCrashDescription:nil];
|
||||
break;
|
||||
case 2: {
|
||||
_crashManagerStatus = BITCrashManagerStatusAutoSend;
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:_crashManagerStatus forKey:kBITCrashManagerStatus];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillSendCrashReportsAlways:)]) {
|
||||
[self.delegate crashManagerWillSendCrashReportsAlways:self];
|
||||
}
|
||||
|
||||
[self sendCrashReports];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
_sendingInProgress = NO;
|
||||
[self cleanCrashReports];
|
||||
case 2:
|
||||
[self handleUserInput:BITCrashManagerUserInputAlwaysSend withUserProvidedCrashDescription:nil];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - Networking
|
||||
|
||||
/**
|
||||
@ -1192,7 +1346,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
*
|
||||
* @param xml The XML data that needs to be send to the server
|
||||
*/
|
||||
- (void)postXML:(NSString*)xml {
|
||||
- (void)postXML:(NSString*)xml attachments:(NSArray *)attachments {
|
||||
NSMutableURLRequest *request = nil;
|
||||
NSString *boundary = @"----FOO";
|
||||
|
||||
@ -1214,12 +1368,28 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
|
||||
[request setValue:contentType forHTTPHeaderField:@"Content-type"];
|
||||
|
||||
NSMutableData *postBody = [NSMutableData data];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] 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:[xml dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
[postBody appendData:[BITHockeyAppClient dataWithPostValue:[xml dataUsingEncoding:NSUTF8StringEncoding]
|
||||
forKey:@"xml"
|
||||
contentType:@"text/xml"
|
||||
boundary:boundary
|
||||
filename:@"crash.xml"]];
|
||||
|
||||
for (NSDictionary *dict in attachments) {
|
||||
NSInteger index = [(NSNumber *)dict[KBITAttachmentDictIndex] integerValue];
|
||||
NSString *key = [NSString stringWithFormat:@"attachment%ld", (long)index];
|
||||
|
||||
BITCrashAttachment *attachment = (BITCrashAttachment *)dict[KBITAttachmentDictAttachment];
|
||||
|
||||
[postBody appendData:[BITHockeyAppClient dataWithPostValue:attachment.attachmentData
|
||||
forKey:key
|
||||
contentType:attachment.contentType
|
||||
boundary:boundary
|
||||
filename:attachment.filename]];
|
||||
}
|
||||
|
||||
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
[request setHTTPBody:postBody];
|
||||
|
||||
_statusCode = 200;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class BITCrashManager;
|
||||
@class BITCrashAttachment;
|
||||
|
||||
/**
|
||||
The `BITCrashManagerDelegate` formal protocol defines methods further configuring
|
||||
@ -47,17 +48,43 @@
|
||||
/** Return any log string based data the crash report being processed should contain
|
||||
|
||||
@param crashManager The `BITCrashManager` instance invoking this delegate
|
||||
@see attachmentForCrashManager:
|
||||
@see userNameForCrashManager:
|
||||
@see userEmailForCrashManager:
|
||||
*/
|
||||
-(NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager;
|
||||
|
||||
|
||||
/** Return a BITCrashAttachment object providing an NSData object the crash report
|
||||
being processed should contain
|
||||
|
||||
Please limit your attachments to reasonable files to avoid high traffic costs for your users.
|
||||
|
||||
Example implementation:
|
||||
|
||||
- (BITCrashAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager {
|
||||
NSData *data = [NSData dataWithContentsOfURL:@"mydatafile"];
|
||||
|
||||
BITCrashAttachment *attachment = [[BITCrashAttachment alloc] initWithFilename:@"myfile.data"
|
||||
attachmentData:data
|
||||
contentType:@"'application/octet-stream"];
|
||||
return attachment;
|
||||
}
|
||||
|
||||
@param crashManager The `BITCrashManager` instance invoking this delegate
|
||||
@see applicationLogForCrashManager:
|
||||
@see userNameForCrashManager:
|
||||
@see userEmailForCrashManager:
|
||||
*/
|
||||
-(BITCrashAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager;
|
||||
|
||||
|
||||
|
||||
/** Return the user name or userid that should be send along each crash report
|
||||
|
||||
@param crashManager The `BITCrashManager` instance invoking this delegate
|
||||
@see applicationLogForCrashManager:
|
||||
@see attachmentForCrashManager:
|
||||
@see userEmailForCrashManager:
|
||||
@deprecated Please use `BITHockeyManagerDelegate userNameForHockeyManager:componentManager:` instead
|
||||
@warning When returning a non nil value, crash reports are not anonymous any
|
||||
@ -71,6 +98,7 @@
|
||||
|
||||
@param crashManager The `BITCrashManager` instance invoking this delegate
|
||||
@see applicationLogForCrashManager:
|
||||
@see attachmentForCrashManager:
|
||||
@see userNameForCrashManager:
|
||||
@deprecated Please use `BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:` instead
|
||||
@warning When returning a non nil value, crash reports are not anonymous any
|
||||
|
@ -31,13 +31,19 @@
|
||||
|
||||
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
|
||||
|
||||
#import <CrashReporter/CrashReporter.h>
|
||||
|
||||
@interface BITCrashManager () {
|
||||
}
|
||||
|
||||
@property (nonatomic) NSUncaughtExceptionHandler *exceptionHandler;
|
||||
|
||||
@property (nonatomic, strong) NSFileManager *fileManager;
|
||||
|
||||
@property (nonatomic, strong) BITPLCrashReporter *plCrashReporter;
|
||||
|
||||
@property (nonatomic) NSString *lastCrashFilename;
|
||||
|
||||
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
|
||||
|
||||
// Only set via BITAuthenticator
|
||||
@ -61,9 +67,17 @@
|
||||
- (BOOL)hasPendingCrashReport;
|
||||
- (BOOL)hasNonApprovedCrashReports;
|
||||
|
||||
- (void)persistUserProvidedCrashDescription:(NSString *)userProvidedCrashDescription;
|
||||
- (void)persistAttachment:(BITCrashAttachment *)attachment withFilename:(NSString *)filename;
|
||||
|
||||
- (BITCrashAttachment *)attachmentForCrashReport:(NSString *)filename;
|
||||
|
||||
- (void)invokeDelayedProcessing;
|
||||
- (void)sendCrashReports;
|
||||
|
||||
- (NSString *)getCrashesDir;
|
||||
- (void)setLastCrashFilename:(NSString *)lastCrashFilename;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -56,6 +56,11 @@
|
||||
@property (nonatomic, copy) NSString *userEmail;
|
||||
|
||||
|
||||
// Fetch user meta data
|
||||
- (BOOL)updateUserIDUsingKeychainAndDelegate;
|
||||
- (BOOL)updateUserNameUsingKeychainAndDelegate;
|
||||
- (BOOL)updateUserEmailUsingKeychainAndDelegate;
|
||||
|
||||
// load new messages from the server
|
||||
- (void)updateMessagesList;
|
||||
|
||||
|
@ -118,8 +118,8 @@
|
||||
|
||||
#pragma mark - Helpers
|
||||
/**
|
||||
* create a post body from the given value, key and boundary
|
||||
* c/p from HockeyBaseManager
|
||||
* create a post body from the given value, key and boundary. This is a convenience call to
|
||||
* dataWithPostValue:forKey:contentType:boundary and aimed at NSString-content.
|
||||
*
|
||||
* @param value -
|
||||
* @param key -
|
||||
@ -128,4 +128,18 @@
|
||||
* @return NSData instance configured to be attached on a (post) URLRequest
|
||||
*/
|
||||
+ (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary;
|
||||
|
||||
/**
|
||||
* create a post body from the given value, key and boundary and content type.
|
||||
*
|
||||
* @param value -
|
||||
* @param key -
|
||||
*@param contentType -
|
||||
* @param boundary -
|
||||
* @param filename -
|
||||
*
|
||||
* @return NSData instance configured to be attached on a (post) URLRequest
|
||||
*/
|
||||
+ (NSData *)dataWithPostValue:(NSData *)value forKey:(NSString *)key contentType:(NSString *)contentType boundary:(NSString *) boundary filename:(NSString *)filename;
|
||||
|
||||
@end
|
||||
|
@ -85,12 +85,25 @@
|
||||
}
|
||||
|
||||
+ (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary {
|
||||
return [self dataWithPostValue:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:key contentType:@"text" boundary:boundary filename:nil];
|
||||
}
|
||||
|
||||
+ (NSData *)dataWithPostValue:(NSData *)value forKey:(NSString *)key contentType:(NSString *)contentType boundary:(NSString *) boundary filename:(NSString *)filename {
|
||||
NSMutableData *postBody = [NSMutableData data];
|
||||
|
||||
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\";\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: text\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[value dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
// There's certainly a better way to check if we are supposed to send binary data here.
|
||||
if (filename){
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", key, filename] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Transfer-Encoding: binary\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
} else {
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
|
||||
[postBody appendData:value];
|
||||
[postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
return postBody;
|
||||
|
@ -38,9 +38,8 @@
|
||||
#import "BITKeychainUtils.h"
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
#import <mach-o/ldsyms.h>
|
||||
#endif
|
||||
#import <mach-o/dyld.h>
|
||||
#import <mach-o/loader.h>
|
||||
|
||||
#ifndef __IPHONE_6_1
|
||||
#define __IPHONE_6_1 60100
|
||||
@ -134,29 +133,35 @@
|
||||
}
|
||||
|
||||
- (NSString *)executableUUID {
|
||||
// This now requires the testing of this feature to be done on an actual device, since it returns always empty strings on the simulator
|
||||
// Once there is a better solution to get unit test targets build without problems this should be changed again, so testing of this
|
||||
// feature is also possible using the simulator
|
||||
// See: http://support.hockeyapp.net/discussions/problems/2306-integrating-hockeyapp-with-test-bundle-target-i386-issues
|
||||
// http://support.hockeyapp.net/discussions/problems/4113-linking-hockeysdk-to-test-bundle-target
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
const uint8_t *command = (const uint8_t *)(&_mh_execute_header + 1);
|
||||
for (uint32_t idx = 0; idx < _mh_execute_header.ncmds; ++idx) {
|
||||
const struct load_command *load_command = (const struct load_command *)command;
|
||||
if (load_command->cmd == LC_UUID) {
|
||||
const struct uuid_command *uuid_command = (const struct uuid_command *)command;
|
||||
const uint8_t *uuid = uuid_command->uuid;
|
||||
const struct mach_header *executableHeader = NULL;
|
||||
for (uint32_t i = 0; i < _dyld_image_count(); i++) {
|
||||
const struct mach_header *header = _dyld_get_image_header(i);
|
||||
if (header->filetype == MH_EXECUTE) {
|
||||
executableHeader = header;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!executableHeader)
|
||||
return @"";
|
||||
|
||||
BOOL is64bit = executableHeader->magic == MH_MAGIC_64 || executableHeader->magic == MH_CIGAM_64;
|
||||
uintptr_t cursor = (uintptr_t)executableHeader + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
|
||||
const struct segment_command *segmentCommand = NULL;
|
||||
for (uint32_t i = 0; i < executableHeader->ncmds; i++, cursor += segmentCommand->cmdsize) {
|
||||
segmentCommand = (struct segment_command *)cursor;
|
||||
if (segmentCommand->cmd == LC_UUID) {
|
||||
const struct uuid_command *uuidCommand = (const struct uuid_command *)segmentCommand;
|
||||
const uint8_t *uuid = uuidCommand->uuid;
|
||||
return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uuid[0], uuid[1], uuid[2], uuid[3],
|
||||
uuid[4], uuid[5], uuid[6], uuid[7],
|
||||
uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]]
|
||||
lowercaseString];
|
||||
} else {
|
||||
command += load_command->cmdsize;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
|
@ -458,10 +458,7 @@ UIImage *bit_newWithContentsOfResolutionIndependentFile(NSString * path) {
|
||||
|
||||
|
||||
UIImage *bit_imageWithContentsOfResolutionIndependentFile(NSString *path) {
|
||||
#ifndef __clang_analyzer__
|
||||
// clang alayzer in 4.2b3 thinks here's a leak, which is not the case.
|
||||
return bit_newWithContentsOfResolutionIndependentFile(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,6 +36,20 @@
|
||||
#import "BITHockeyAppClient.h"
|
||||
#import "BITKeychainUtils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t info_version;
|
||||
const char hockey_version[16];
|
||||
const char hockey_build[16];
|
||||
} bitstadium_info_t;
|
||||
|
||||
bitstadium_info_t bitstadium_library_info __attribute__((section("__TEXT,__bit_hockey,regular,no_dead_strip"))) = {
|
||||
.info_version = 1,
|
||||
.hockey_version = BITHOCKEY_C_VERSION,
|
||||
.hockey_build = BITHOCKEY_C_BUILD
|
||||
};
|
||||
|
||||
|
||||
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
|
||||
#import "BITCrashManagerPrivate.h"
|
||||
@ -417,11 +431,11 @@
|
||||
|
||||
|
||||
- (NSString *)version {
|
||||
return BITHOCKEY_VERSION;
|
||||
return [NSString stringWithUTF8String:bitstadium_library_info.hockey_version];
|
||||
}
|
||||
|
||||
- (NSString *)build {
|
||||
return BITHOCKEY_BUILD;
|
||||
return [NSString stringWithUTF8String:bitstadium_library_info.hockey_build];
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,7 +155,7 @@
|
||||
if ([self.userDefaults objectForKey:kBITStoreUpdateLastUUID]) {
|
||||
lastSavedUUID = [self.userDefaults objectForKey:kBITStoreUpdateLastUUID];
|
||||
|
||||
if (lastSavedUUID && ![lastSavedUUID isEqualToString:_currentUUID]) {
|
||||
if (lastSavedUUID && [lastSavedUUID length] > 0 && ![lastSavedUUID isEqualToString:_currentUUID]) {
|
||||
// the UUIDs don't match, store the new one
|
||||
[self.userDefaults setObject:_currentUUID forKey:kBITStoreUpdateLastUUID];
|
||||
|
||||
|
@ -669,7 +669,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
|
||||
self.checkInProgress = YES;
|
||||
|
||||
// do we need to update?
|
||||
if (![self checkForTracker] && ![self shouldCheckForUpdates] && !_currentHockeyViewController) {
|
||||
if (![self checkForTracker] && !_currentHockeyViewController && ![self shouldCheckForUpdates] && _updateSetting != BITUpdateCheckManually) {
|
||||
BITHockeyLog(@"INFO: Update not needed right now");
|
||||
self.checkInProgress = NO;
|
||||
return;
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
|
||||
#import "BITCrashManager.h"
|
||||
#import "BITCrashAttachment.h"
|
||||
#import "BITCrashManagerDelegate.h"
|
||||
#import "BITCrashDetails.h"
|
||||
#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
|
||||
|
@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'HockeySDK'
|
||||
s.version = '3.5.4'
|
||||
s.version = '3.5.5'
|
||||
|
||||
s.summary = 'Collect live crash reports, get feedback from your users, distribute your betas, and analyze your test coverage with HockeyApp.'
|
||||
s.description = <<-DESC
|
||||
@ -12,19 +12,19 @@ Pod::Spec.new do |s|
|
||||
DESC
|
||||
|
||||
s.homepage = 'http://hockeyapp.net/'
|
||||
s.documentation_url = 'http://hockeyapp.net/help/sdk/ios/3.5.4/'
|
||||
s.documentation_url = 'http://hockeyapp.net/help/sdk/ios/3.5.5/'
|
||||
|
||||
s.license = 'MIT'
|
||||
s.author = { 'Andreas Linde' => 'mail@andreaslinde.de', 'Thomas Dohmke' => "thomas@dohmke.de" }
|
||||
s.source = { :git => 'https://github.com/bitstadium/HockeySDK-iOS.git', :tag => s.version.to_s }
|
||||
|
||||
s.platform = :ios, '5.0'
|
||||
s.source_files = 'Classes'
|
||||
s.source_files = 'Classes', "Vendor/CrashReporter.framework/Versions/A/Headers/*.h"
|
||||
s.requires_arc = true
|
||||
|
||||
s.frameworks = 'CoreText', 'QuartzCore', 'SystemConfiguration', 'CoreGraphics', 'UIKit', 'Security'
|
||||
s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework'
|
||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"27\\""} }
|
||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"28\\"" BITHOCKEY_C_BUILD="\\"28\\""} }
|
||||
s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] }
|
||||
s.preserve_paths = 'Resources', 'Support'
|
||||
|
||||
|
14
README.md
14
README.md
@ -1,6 +1,6 @@
|
||||
## Version 3.5.4
|
||||
## Version 3.5.5
|
||||
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Changelog.html)
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Changelog.html)
|
||||
|
||||
|
||||
## Introduction
|
||||
@ -31,10 +31,10 @@ The main SDK class is `BITHockeyManager`. It initializes all modules and provide
|
||||
|
||||
## Installation & Setup
|
||||
|
||||
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Guide-Installation-Setup.html) (Recommended)
|
||||
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Guide-Installation-Setup-Advanced.html) (Using Git submodule and Xcode sub-project)
|
||||
- [Identify and authenticate users of Ad-Hoc or Enterprise builds](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
|
||||
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Guide-Migration-Kits.html)
|
||||
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Guide-Installation-Setup.html) (Recommended)
|
||||
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Guide-Installation-Setup-Advanced.html) (Using Git submodule and Xcode sub-project)
|
||||
- [Identify and authenticate users of Ad-Hoc or Enterprise builds](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
|
||||
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Guide-Migration-Kits.html)
|
||||
- [Mac Desktop Uploader](http://support.hockeyapp.net/kb/how-tos/how-to-upload-to-hockeyapp-on-a-mac)
|
||||
|
||||
|
||||
@ -48,4 +48,4 @@ This documentation provides integrated help in Xcode for all public APIs and a s
|
||||
|
||||
3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets`
|
||||
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.4/](http://hockeyapp.net/help/sdk/ios/3.5.4/)
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.5/](http://hockeyapp.net/help/sdk/ios/3.5.5/)
|
||||
|
0
Resources/nl.lproj/HockeySDK.strings
Executable file → Normal file
0
Resources/nl.lproj/HockeySDK.strings
Executable file → Normal file
0
Resources/ro.lproj/HockeySDK.strings
Executable file → Normal file
0
Resources/ro.lproj/HockeySDK.strings
Executable file → Normal file
@ -95,10 +95,10 @@
|
||||
1E5955D015B71C8600A03429 /* IconGradient@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C515B71C8600A03429 /* IconGradient@2x.png */; };
|
||||
1E5955FD15B7877B00A03429 /* BITHockeyManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */; };
|
||||
1E5A459416F0DFC200B55C04 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459316F0DFC200B55C04 /* UIKit.framework */; };
|
||||
1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; };
|
||||
1E5A459B16F0DFC200B55C04 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E5A459916F0DFC200B55C04 /* InfoPlist.strings */; };
|
||||
1E5A459E16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */; };
|
||||
1E61CCAF18E0585A00A5E38E /* BITFeedbackManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E61CCAE18E0585A00A5E38E /* BITFeedbackManagerTests.m */; };
|
||||
1E70A23217F2F982001BB32D /* live_report_empty.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A22F17F2F982001BB32D /* live_report_empty.plcrash */; };
|
||||
1E70A23317F2F982001BB32D /* live_report_exception.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A23017F2F982001BB32D /* live_report_exception.plcrash */; };
|
||||
1E70A23417F2F982001BB32D /* live_report_signal.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A23117F2F982001BB32D /* live_report_signal.plcrash */; };
|
||||
@ -129,6 +129,8 @@
|
||||
1EAF20AA162DC0F600957B1D /* feedbackActiviy.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */; };
|
||||
1EAF20AB162DC0F600957B1D /* feedbackActiviy@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */; };
|
||||
1EB52FD5167B766100C801D5 /* HockeySDK.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E59555F15B6F80E00A03429 /* HockeySDK.strings */; };
|
||||
1ED570C718BF878C00AB3350 /* BITCrashAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ED570C518BF878C00AB3350 /* BITCrashAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1ED570C818BF878C00AB3350 /* BITCrashAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */; };
|
||||
1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */; };
|
||||
1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -248,11 +250,11 @@
|
||||
1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerDelegate.h; sourceTree = "<group>"; };
|
||||
1E5A459016F0DFC200B55C04 /* HockeySDKTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HockeySDKTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
1E5A459316F0DFC200B55C04 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
1E5A459816F0DFC200B55C04 /* HockeySDKTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDKTests-Info.plist"; sourceTree = "<group>"; };
|
||||
1E5A459A16F0DFC200B55C04 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BITStoreUpdateManagerTests.m; sourceTree = "<group>"; };
|
||||
1E5A459F16F0DFC200B55C04 /* HockeySDKTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HockeySDKTests-Prefix.pch"; sourceTree = "<group>"; };
|
||||
1E61CCAE18E0585A00A5E38E /* BITFeedbackManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackManagerTests.m; sourceTree = "<group>"; };
|
||||
1E66CA9115D4100500F35BED /* buildnumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = buildnumber.xcconfig; sourceTree = "<group>"; };
|
||||
1E6DDCEE169E290C0076C65D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/HockeySDK.strings; sourceTree = "<group>"; };
|
||||
1E6F0450167B5E5600ED1C86 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/HockeySDK.strings"; sourceTree = "<group>"; };
|
||||
@ -287,6 +289,8 @@
|
||||
1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = feedbackActiviy.png; sourceTree = "<group>"; };
|
||||
1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "feedbackActiviy@2x.png"; sourceTree = "<group>"; };
|
||||
1EB52FC3167B73D400C801D5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HockeySDK.strings; sourceTree = "<group>"; };
|
||||
1ED570C518BF878C00AB3350 /* BITCrashAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITCrashAttachment.h; sourceTree = "<group>"; };
|
||||
1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITCrashAttachment.m; sourceTree = "<group>"; };
|
||||
1EDA60CF15C2C1450032D10B /* HockeySDK-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDK-Info.plist"; sourceTree = "<group>"; };
|
||||
1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackActivity.h; sourceTree = "<group>"; };
|
||||
1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackActivity.m; sourceTree = "<group>"; };
|
||||
@ -336,7 +340,6 @@
|
||||
files = (
|
||||
1EA1170016F4D32C001C015C /* libHockeySDK.a in Frameworks */,
|
||||
1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */,
|
||||
1E5A459416F0DFC200B55C04 /* UIKit.framework in Frameworks */,
|
||||
1EA1170116F4D354001C015C /* CrashReporter.framework in Frameworks */,
|
||||
1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */,
|
||||
1E7A45FC16F54FB5005B08F1 /* OCHamcrestIOS.framework in Frameworks */,
|
||||
@ -381,6 +384,7 @@
|
||||
1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */,
|
||||
E48A3DEE17B3EFF100924C3D /* BITAuthenticatorTests.m */,
|
||||
1EFF03E417F2485500A5F13C /* BITCrashManagerTests.m */,
|
||||
1E61CCAE18E0585A00A5E38E /* BITFeedbackManagerTests.m */,
|
||||
E40E0B0817DA19DC005E38C1 /* BITHockeyAppClientTests.m */,
|
||||
E4507E4217F0658F00171A0D /* BITKeychainUtilsTests.m */,
|
||||
1E70A23517F31B82001BB32D /* BITHockeyHelperTests.m */,
|
||||
@ -486,6 +490,8 @@
|
||||
1E90FD7218EDB86400CF0417 /* BITCrashDetails.m */,
|
||||
1EFF03D717F20F8300A5F13C /* BITCrashManagerPrivate.h */,
|
||||
1E754E581621FBB70070AB92 /* BITCrashManagerDelegate.h */,
|
||||
1ED570C518BF878C00AB3350 /* BITCrashAttachment.h */,
|
||||
1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */,
|
||||
1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */,
|
||||
1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */,
|
||||
);
|
||||
@ -566,7 +572,6 @@
|
||||
E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */,
|
||||
E400561D148D79B500EB22B9 /* Foundation.framework */,
|
||||
1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */,
|
||||
1E5A459316F0DFC200B55C04 /* UIKit.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@ -655,6 +660,7 @@
|
||||
1E49A4AF161222B900463151 /* BITHockeyBaseManager.h in Headers */,
|
||||
1E49A4B8161222B900463151 /* BITHockeyBaseViewController.h in Headers */,
|
||||
1E94F9E116E91330006570AD /* BITStoreUpdateManager.h in Headers */,
|
||||
1ED570C718BF878C00AB3350 /* BITCrashAttachment.h in Headers */,
|
||||
1E0829001708F69A0073050E /* BITStoreUpdateManagerDelegate.h in Headers */,
|
||||
1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */,
|
||||
1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */,
|
||||
@ -744,7 +750,7 @@
|
||||
E4005611148D79B500EB22B9 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0500;
|
||||
LastUpgradeCheck = 0510;
|
||||
};
|
||||
buildConfigurationList = E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@ -840,7 +846,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nPLCR_DIR=${SRCROOT}/../Vendor/CrashReporter.framework\nZIP_FOLDER=HockeySDK-iOS\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nHEADERS_DIR=${WRK_DIR}/Release-iphoneos/usr/local/include\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${PLCR_DIR}/Versions/A/Headers/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n# copy license, changelog, documentation, integration json\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n\n#copy to output dir on cisimple\nif [ $CISIMPLE ]; then\n if [ ! -d \"${CONFIGURATION_BUILD_DIR}\" ]; then\n mkdir \"${CONFIGURATION_BUILD_DIR}\"\n fi\n cd \"${PRODUCTS_DIR}\"\n cp \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${CONFIGURATION_BUILD_DIR}/${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nfi";
|
||||
shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nZIP_FOLDER=HockeySDK-iOS\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nHEADERS_DIR=${WRK_DIR}/Release-iphoneos/usr/local/include\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n# copy license, changelog, documentation, integration json\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n";
|
||||
};
|
||||
1E8E66B215BC3D8200632A2E /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@ -883,6 +889,7 @@
|
||||
1E49A4511612223B00463151 /* BITFeedbackManager.m in Sources */,
|
||||
E4933E8117B66CDA00B11ACC /* BITHTTPOperation.m in Sources */,
|
||||
1E49A45A1612223B00463151 /* BITFeedbackMessage.m in Sources */,
|
||||
1ED570C818BF878C00AB3350 /* BITCrashAttachment.m in Sources */,
|
||||
1E49A4601612223B00463151 /* BITFeedbackUserDataViewController.m in Sources */,
|
||||
1E49A4701612226D00463151 /* BITAppVersionMetaInfo.m in Sources */,
|
||||
1E49A4761612226D00463151 /* BITUpdateManager.m in Sources */,
|
||||
@ -923,6 +930,7 @@
|
||||
1E70A23617F31B82001BB32D /* BITHockeyHelperTests.m in Sources */,
|
||||
E48A3DEF17B3EFF100924C3D /* BITAuthenticatorTests.m in Sources */,
|
||||
1EA1170716F53B91001C015C /* BITTestHelper.m in Sources */,
|
||||
1E61CCAF18E0585A00A5E38E /* BITFeedbackManagerTests.m in Sources */,
|
||||
E4507E4317F0658F00171A0D /* BITKeychainUtilsTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0500"
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0500"
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0500"
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0500"
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#import "BITTestHelper.h"
|
||||
|
||||
#define kBITCrashMetaAttachment @"BITCrashMetaAttachment"
|
||||
|
||||
@interface BITCrashManagerTests : SenTestCase
|
||||
|
||||
@ -71,7 +72,6 @@
|
||||
[self startManager];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Setup Tests
|
||||
|
||||
- (void)testThatItInstantiates {
|
||||
@ -81,6 +81,32 @@
|
||||
|
||||
#pragma mark - Persistence tests
|
||||
|
||||
- (void)testPersistUserProvidedCrashDescription {
|
||||
NSString *tempCrashName = @"tempCrash";
|
||||
[_sut setLastCrashFilename:tempCrashName];
|
||||
[_sut persistUserProvidedCrashDescription:@"Test string"];
|
||||
|
||||
NSError *error;
|
||||
NSString *description = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%@.desc", [[_sut getCrashesDir] stringByAppendingPathComponent: tempCrashName]] encoding:NSUTF8StringEncoding error:&error];
|
||||
assertThat(description, equalTo(@"Test string"));
|
||||
}
|
||||
|
||||
- (void)testPersistAttachment {
|
||||
NSString *filename = @"TestAttachment";
|
||||
NSData *data = [[NSData alloc] initWithBase64Encoding:@"TestData"];
|
||||
NSString* type = @"text/plain";
|
||||
|
||||
BITCrashAttachment *originalAttachment = [[BITCrashAttachment alloc] initWithFilename:filename attachmentData:data contentType:type];
|
||||
NSString *attachmentFilename = [_sut.getCrashesDir stringByAppendingPathComponent:@"testAttachment"];
|
||||
|
||||
[_sut persistAttachment:originalAttachment withFilename:attachmentFilename];
|
||||
|
||||
BITCrashAttachment *decodedAttachment = [_sut attachmentForCrashReport:attachmentFilename];
|
||||
|
||||
assertThat(decodedAttachment.filename, equalTo(filename));
|
||||
assertThat(decodedAttachment.attachmentData, equalTo(data));
|
||||
assertThat(decodedAttachment.contentType, equalTo(type));
|
||||
}
|
||||
|
||||
#pragma mark - Helper
|
||||
|
||||
@ -123,6 +149,44 @@
|
||||
[verifyCount(delegateMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
#pragma mark - Handle User Input
|
||||
|
||||
- (void)testHandleUserInputDontSend {
|
||||
id <BITCrashManagerDelegate> delegateMock = mockProtocol(@protocol(BITCrashManagerDelegate));
|
||||
_sut.delegate = delegateMock;
|
||||
|
||||
assertThatBool([_sut handleUserInput:BITCrashManagerUserInputDontSend withUserProvidedCrashDescription:nil], equalToBool(YES));
|
||||
|
||||
[verify(delegateMock) crashManagerWillCancelSendingCrashReport:_sut];
|
||||
|
||||
}
|
||||
|
||||
- (void)testHandleUserInputSend {
|
||||
assertThatBool([_sut handleUserInput:BITCrashManagerUserInputSend withUserProvidedCrashDescription:nil], equalToBool(YES));
|
||||
}
|
||||
|
||||
- (void)testHandleUserInputAlwaysSend {
|
||||
id <BITCrashManagerDelegate> delegateMock = mockProtocol(@protocol(BITCrashManagerDelegate));
|
||||
_sut.delegate = delegateMock;
|
||||
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
|
||||
|
||||
//Test if CrashManagerStatus is unset
|
||||
[given([mockUserDefaults integerForKey:@"BITCrashManagerStatus"]) willReturn:nil];
|
||||
|
||||
//Test if method runs through
|
||||
assertThatBool([_sut handleUserInput:BITCrashManagerUserInputAlwaysSend withUserProvidedCrashDescription:nil], equalToBool(YES));
|
||||
|
||||
//Test if correct CrashManagerStatus is now set
|
||||
[given([mockUserDefaults integerForKey:@"BITCrashManagerStauts"]) willReturnInt:BITCrashManagerStatusAutoSend];
|
||||
|
||||
//Verify that delegate method has been called
|
||||
[verify(delegateMock) crashManagerWillSendCrashReportsAlways:_sut];
|
||||
|
||||
}
|
||||
|
||||
- (void)testHandleUserInputWithInvalidInput {
|
||||
assertThatBool([_sut handleUserInput:3 withUserProvidedCrashDescription:nil], equalToBool(NO));
|
||||
}
|
||||
|
||||
#pragma mark - Debugger
|
||||
|
||||
@ -201,6 +265,7 @@
|
||||
[_sut handleCrashReport];
|
||||
|
||||
[verifyCount(delegateMock, times(1)) applicationLogForCrashManager:_sut];
|
||||
[verifyCount(delegateMock, times(1)) attachmentForCrashManager:_sut];
|
||||
|
||||
// we should have now 1 pending crash report
|
||||
assertThatBool([_sut hasPendingCrashReport], equalToBool(YES));
|
||||
|
216
Support/HockeySDKTests/BITFeedbackManagerTests.m
Normal file
216
Support/HockeySDKTests/BITFeedbackManagerTests.m
Normal file
@ -0,0 +1,216 @@
|
||||
//
|
||||
// BITFeedbackManagerTests.m
|
||||
// HockeySDK
|
||||
//
|
||||
// Created by Andreas Linde on 24.03.14.
|
||||
//
|
||||
//
|
||||
|
||||
#import <SenTestingKit/SenTestingKit.h>
|
||||
|
||||
#define HC_SHORTHAND
|
||||
#import <OCHamcrestIOS/OCHamcrestIOS.h>
|
||||
|
||||
#define MOCKITO_SHORTHAND
|
||||
#import <OCMockitoIOS/OCMockitoIOS.h>
|
||||
|
||||
#import "HockeySDK.h"
|
||||
#import "HockeySDKPrivate.h"
|
||||
#import "BITFeedbackManager.h"
|
||||
#import "BITFeedbackManagerPrivate.h"
|
||||
#import "BITHockeyBaseManager.h"
|
||||
#import "BITHockeyBaseManagerPrivate.h"
|
||||
|
||||
#import "BITTestHelper.h"
|
||||
|
||||
@interface BITFeedbackManagerTests : SenTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation BITFeedbackManagerTests {
|
||||
BITFeedbackManager *_sut;
|
||||
}
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
hm.delegate = nil;
|
||||
_sut = [[BITFeedbackManager alloc] initWithAppIdentifier:nil isAppStoreEnvironment:NO];
|
||||
_sut.delegate = nil;
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wimplicit"
|
||||
__gcov_flush();
|
||||
# pragma clang diagnostic pop
|
||||
|
||||
[_sut removeKeyFromKeychain:kBITHockeyMetaUserID];
|
||||
[_sut removeKeyFromKeychain:kBITHockeyMetaUserName];
|
||||
[_sut removeKeyFromKeychain:kBITHockeyMetaUserEmail];
|
||||
|
||||
_sut = nil;
|
||||
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)startManager {
|
||||
[_sut startManager];
|
||||
}
|
||||
|
||||
#pragma mark - Setup Tests
|
||||
|
||||
|
||||
#pragma mark - User Metadata
|
||||
|
||||
- (void)testUpdateUserIDWithNoDataPresent {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
id delegateMock = mockProtocol(@protocol(BITHockeyManagerDelegate));
|
||||
hm.delegate = delegateMock;
|
||||
_sut.delegate = delegateMock;
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(NO));
|
||||
assertThat(_sut.userID, nilValue());
|
||||
|
||||
[verifyCount(delegateMock, times(1)) userIDForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
- (void)testUpdateUserIDWithDelegateReturningData {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
NSObject <BITHockeyManagerDelegate> *classMock = mockObjectAndProtocol([NSObject class], @protocol(BITHockeyManagerDelegate));
|
||||
[given([classMock userIDForHockeyManager:hm componentManager:_sut]) willReturn:@"test"];
|
||||
hm.delegate = classMock;
|
||||
_sut.delegate = classMock;
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userID, equalTo(@"test"));
|
||||
|
||||
[verifyCount(classMock, times(1)) userIDForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
- (void)testUpdateUserIDWithValueInKeychain {
|
||||
[_sut addStringValueToKeychain:@"test" forKey:kBITHockeyMetaUserID];
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userID, equalTo(@"test"));
|
||||
}
|
||||
|
||||
- (void)testUpdateUserIDWithGlobalSetter {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
[hm setUserID:@"test"];
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userID, equalTo(@"test"));
|
||||
}
|
||||
|
||||
|
||||
- (void)testUpdateUserNameWithNoDataPresent {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
id delegateMock = mockProtocol(@protocol(BITHockeyManagerDelegate));
|
||||
hm.delegate = delegateMock;
|
||||
_sut.delegate = delegateMock;
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(NO));
|
||||
assertThat(_sut.userName, nilValue());
|
||||
|
||||
[verifyCount(delegateMock, times(1)) userNameForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
- (void)testUpdateUserNameWithDelegateReturningData {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
NSObject <BITHockeyManagerDelegate> *classMock = mockObjectAndProtocol([NSObject class], @protocol(BITHockeyManagerDelegate));
|
||||
[given([classMock userNameForHockeyManager:hm componentManager:_sut]) willReturn:@"test"];
|
||||
hm.delegate = classMock;
|
||||
_sut.delegate = classMock;
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userName, equalTo(@"test"));
|
||||
|
||||
[verifyCount(classMock, times(1)) userNameForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
- (void)testUpdateUserNameWithValueInKeychain {
|
||||
[_sut addStringValueToKeychain:@"test" forKey:kBITHockeyMetaUserName];
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userName, equalTo(@"test"));
|
||||
}
|
||||
|
||||
- (void)testUpdateUserNameWithGlobalSetter {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
[hm setUserName:@"test"];
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userName, equalTo(@"test"));
|
||||
}
|
||||
|
||||
|
||||
- (void)testUpdateUserEmailWithNoDataPresent {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
id delegateMock = mockProtocol(@protocol(BITHockeyManagerDelegate));
|
||||
hm.delegate = delegateMock;
|
||||
_sut.delegate = delegateMock;
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(NO));
|
||||
assertThat(_sut.userEmail, nilValue());
|
||||
|
||||
[verifyCount(delegateMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
- (void)testUpdateUserEmailWithDelegateReturningData {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
NSObject <BITHockeyManagerDelegate> *classMock = mockObjectAndProtocol([NSObject class], @protocol(BITHockeyManagerDelegate));
|
||||
[given([classMock userEmailForHockeyManager:hm componentManager:_sut]) willReturn:@"test"];
|
||||
hm.delegate = classMock;
|
||||
_sut.delegate = classMock;
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userEmail, equalTo(@"test"));
|
||||
|
||||
[verifyCount(classMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut];
|
||||
}
|
||||
|
||||
- (void)testUpdateUserEmailWithValueInKeychain {
|
||||
[_sut addStringValueToKeychain:@"test" forKey:kBITHockeyMetaUserEmail];
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userEmail, equalTo(@"test"));
|
||||
}
|
||||
|
||||
- (void)testUpdateUserEmailWithGlobalSetter {
|
||||
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
|
||||
[hm setUserEmail:@"test"];
|
||||
|
||||
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
|
||||
|
||||
assertThatBool(dataAvailable, equalToBool(YES));
|
||||
assertThat(_sut.userEmail, equalTo(@"test"));
|
||||
}
|
||||
|
||||
|
||||
@end
|
@ -32,7 +32,12 @@
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here; it will be run once, after the last test case.
|
||||
// Tear-down code here.
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wimplicit"
|
||||
__gcov_flush();
|
||||
# pragma clang diagnostic pop
|
||||
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@
|
||||
STAssertFalse(result, @"The newer version is being ignored");
|
||||
}
|
||||
|
||||
- (void)testReportedVersionIsNewerThanTHeIgnoredVersion {
|
||||
- (void)testReportedVersionIsNewerThanTheIgnoredVersion {
|
||||
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
|
||||
[given([mockUserDefaults objectForKey:@"BITStoreUpdateLastStoreVersion"]) willReturn:@"4.1.1"];
|
||||
[given([mockUserDefaults objectForKey:@"BITStoreUpdateLastUUID"]) willReturn:@""];
|
||||
|
0
Support/HockeySDKTests/OCHamcrestIOS.framework/Versions/A/Headers/HCInvocationMatcher.h
Executable file → Normal file
0
Support/HockeySDKTests/OCHamcrestIOS.framework/Versions/A/Headers/HCInvocationMatcher.h
Executable file → Normal file
@ -1,8 +1,8 @@
|
||||
#include "HockeySDK.xcconfig"
|
||||
|
||||
BUILD_NUMBER = 27
|
||||
VERSION_STRING = 3.5.4
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\""
|
||||
BUILD_NUMBER = 28
|
||||
VERSION_STRING = 3.5.5
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\"" BITHOCKEY_C_VERSION="\""$(VERSION_STRING)"\"" BITHOCKEY_C_BUILD="\""$(BUILD_NUMBER)"\""
|
||||
BIT_ARM_ARCHS = armv7 armv7s arm64
|
||||
BIT_SIM_ARCHS = x86_64 i386
|
||||
ARCHS = $(BIT_ARM_ARCHS)
|
||||
|
Binary file not shown.
@ -32,7 +32,7 @@
|
||||
|
||||
@interface PLCrashReportProcessInfo : NSObject {
|
||||
@private
|
||||
/** Process name */
|
||||
/** Process name, or nil if unavailable. */
|
||||
NSString *_processName;
|
||||
|
||||
/** Process ID */
|
||||
@ -45,7 +45,7 @@
|
||||
* will be nil. */
|
||||
NSDate *_processStartTime;
|
||||
|
||||
/** Parent process name */
|
||||
/** Parent process name, or nil if unavailable. */
|
||||
NSString *_parentProcessName;
|
||||
|
||||
/** Parent process ID */
|
||||
|
@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>13B42</string>
|
||||
<string>13C64</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
@ -23,16 +23,16 @@
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>5A3005</string>
|
||||
<string>5B1008</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>13A595</string>
|
||||
<string>13C64</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.9</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0502</string>
|
||||
<string>0511</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>5A3005</string>
|
||||
<string>5B1008</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
0
Vendor/XcodeCoverage/.gitignore
vendored
Executable file → Normal file
0
Vendor/XcodeCoverage/.gitignore
vendored
Executable file → Normal file
0
Vendor/XcodeCoverage/LICENSE.txt
vendored
Executable file → Normal file
0
Vendor/XcodeCoverage/LICENSE.txt
vendored
Executable file → Normal file
0
Vendor/XcodeCoverage/README.md
vendored
Executable file → Normal file
0
Vendor/XcodeCoverage/README.md
vendored
Executable file → Normal file
5
Vendor/XcodeCoverage/cleancov
vendored
5
Vendor/XcodeCoverage/cleancov
vendored
@ -5,6 +5,7 @@
|
||||
# Source: https://github.com/jonreid/XcodeCoverage
|
||||
#
|
||||
|
||||
source envcov.sh
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source ${DIR}/envcov.sh
|
||||
|
||||
"${LCOV}" --zerocounters -d "${OBJ_DIR}"
|
||||
"${LCOV}" --zerocounters -d "${OBJ_DIR}"
|
5
Vendor/XcodeCoverage/envcov.sh
vendored
5
Vendor/XcodeCoverage/envcov.sh
vendored
@ -4,11 +4,12 @@
|
||||
# Source: https://github.com/jonreid/XcodeCoverage
|
||||
#
|
||||
|
||||
source env.sh
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source ${DIR}/env.sh
|
||||
|
||||
# Change the report name if you like:
|
||||
LCOV_INFO=Coverage.info
|
||||
|
||||
LCOV_PATH=${SRCROOT}/../Vendor/XcodeCoverage/lcov-1.10/bin
|
||||
LCOV=${LCOV_PATH}/lcov
|
||||
OBJ_DIR=${OBJECT_FILE_DIR_normal}/${CURRENT_ARCH}
|
||||
OBJ_DIR=${OBJECT_FILE_DIR_normal}/${CURRENT_ARCH}
|
3
Vendor/XcodeCoverage/exportenv.sh
vendored
3
Vendor/XcodeCoverage/exportenv.sh
vendored
@ -4,4 +4,5 @@
|
||||
# Source: https://github.com/jonreid/XcodeCoverage
|
||||
#
|
||||
|
||||
export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > ../Vendor/XcodeCoverage/env.sh
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > ${DIR}/env.sh
|
5
Vendor/XcodeCoverage/getcov
vendored
5
Vendor/XcodeCoverage/getcov
vendored
@ -5,7 +5,8 @@
|
||||
# Source: https://github.com/jonreid/XcodeCoverage
|
||||
#
|
||||
|
||||
source envcov.sh
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source ${DIR}/envcov.sh
|
||||
|
||||
remove_old_report()
|
||||
{
|
||||
@ -45,4 +46,4 @@ remove_old_report
|
||||
enter_lcov_dir
|
||||
gather_coverage
|
||||
exclude_data
|
||||
generate_report
|
||||
generate_report
|
52
Vendor/XcodeCoverage/lcov-1.10/bin/geninfo
vendored
52
Vendor/XcodeCoverage/lcov-1.10/bin/geninfo
vendored
@ -1017,7 +1017,7 @@ sub process_dafile($$)
|
||||
warn("WARNING: GCOV failed for $da_filename!\n");
|
||||
return;
|
||||
}
|
||||
die("ERROR: GCOV failed for $da_filename!\n");
|
||||
warn("WARNING: GCOV failed for $da_filename!\n");
|
||||
}
|
||||
|
||||
# Collect data from resulting .gcov files and create .info file
|
||||
@ -1861,33 +1861,37 @@ sub read_gcov_file($)
|
||||
|
||||
sub get_gcov_version()
|
||||
{
|
||||
local *HANDLE;
|
||||
my $version_string;
|
||||
my $result;
|
||||
local *HANDLE;
|
||||
my $version_string;
|
||||
my $result;
|
||||
|
||||
open(GCOV_PIPE, "-|", "$gcov_tool -v")
|
||||
or die("ERROR: cannot retrieve gcov version!\n");
|
||||
$version_string = <GCOV_PIPE>;
|
||||
close(GCOV_PIPE);
|
||||
open(GCOV_PIPE, "-|", "$gcov_tool --version")
|
||||
or die("ERROR: cannot retrieve gcov version!\n");
|
||||
$version_string = <GCOV_PIPE>;
|
||||
close(GCOV_PIPE);
|
||||
|
||||
$result = 0;
|
||||
if ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)
|
||||
{
|
||||
if (defined($4))
|
||||
{
|
||||
info("Found gcov version: $1.$2.$4\n");
|
||||
$result = $1 << 16 | $2 << 8 | $4;
|
||||
}
|
||||
else
|
||||
{
|
||||
info("Found gcov version: $1.$2\n");
|
||||
$result = $1 << 16 | $2 << 8;
|
||||
}
|
||||
}
|
||||
return ($result, $version_string);
|
||||
$result = 0;
|
||||
if ($version_string =~ m/LLVM/)
|
||||
{
|
||||
info("Found llvm-cov\n");
|
||||
$result = 0x40201;
|
||||
}
|
||||
elsif ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)
|
||||
{
|
||||
if (defined($4))
|
||||
{
|
||||
info("Found gcov version: $1.$2.$4\n");
|
||||
$result = $1 << 16 | $2 << 8 | $4;
|
||||
}
|
||||
else
|
||||
{
|
||||
info("Found gcov version: $1.$2\n");
|
||||
$result = $1 << 16 | $2 << 8;
|
||||
}
|
||||
}
|
||||
return ($result, $version_string);
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# info(printf_parameter)
|
||||
#
|
||||
|
@ -1,3 +1,14 @@
|
||||
## Version 3.5.5
|
||||
|
||||
- [NEW] `BITCrashManager`: Added support for adding a binary attachment to crash reports
|
||||
- [NEW] `BITCrashManager`: Integrated PLCrashReporter 1.2 RC5 (with 2 more fixes)
|
||||
- [BUGFIX] `BITUpdateManager`: Fixed problem with `checkForUpdate` when `updateSetting` is set to `BITUpdateCheckManually`
|
||||
- [BUGFIX] `BITAuthenticator`: Fixed keychain warning alert showing app on launch if keychain is locked
|
||||
- [BUGFIX] `BITAuthenticator`: Fixed a possible assertion problem with auto-authentication (when using custom SDK builds without assertions being disabled)
|
||||
- [BUGFIX] `BITAuthenticator`: Added user email to crash report for beta builds if BITAuthenticator is set to BITAuthenticatorIdentificationTypeWebAuth
|
||||
- [BUGFIX] Fixed more analyzer warnings
|
||||
<br /><br/>
|
||||
|
||||
## Version 3.5.4
|
||||
|
||||
- [BUGFIX] Fix a possible crash before sending the crash report when the selector could not be found
|
||||
|
@ -1,6 +1,6 @@
|
||||
## Version 3.5.4
|
||||
## Version 3.5.5
|
||||
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Changelog.html)
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Changelog.html)
|
||||
|
||||
## Introduction
|
||||
|
||||
@ -116,7 +116,7 @@ This documentation provides integrated help in Xcode for all public APIs and a s
|
||||
|
||||
3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets`
|
||||
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.4/](http://hockeyapp.net/help/sdk/ios/3.5.4/)
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.5/](http://hockeyapp.net/help/sdk/ios/3.5.5/)
|
||||
|
||||
### Set up with xcconfig
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
## Version 3.5.4
|
||||
## Version 3.5.5
|
||||
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Changelog.html)
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Changelog.html)
|
||||
|
||||
## Introduction
|
||||
|
||||
@ -90,9 +90,9 @@ The Mac Desktop Uploader can provide easy uploading of your app versions to Hock
|
||||
|
||||
This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and how-tos.
|
||||
|
||||
1. Copy `de.bitstadium.HockeySDK-iOS-3.5.1.docset` into ~`/Library/Developer/Shared/Documentation/DocSets`
|
||||
1. Copy `de.bitstadium.HockeySDK-iOS-3.5.5.docset` into ~`/Library/Developer/Shared/Documentation/DocSets`
|
||||
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.4/](http://hockeyapp.net/help/sdk/ios/3.5.4/)
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.5/](http://hockeyapp.net/help/sdk/ios/3.5.5/)
|
||||
|
||||
### Set up with xcconfig
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user