mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-02 04:38:33 +00:00
Merge pull request #167 from bitstadium/feature/cxx-exception-support
Add C++ Exception support
This commit is contained in:
commit
12e6f7bf67
@ -4,10 +4,10 @@ before_install:
|
|||||||
script:
|
script:
|
||||||
- set -o pipefail
|
- set -o pipefail
|
||||||
- cd Support
|
- cd Support
|
||||||
- xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK" -sdk iphonesimulator
|
|
||||||
-configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" test |
|
|
||||||
xcpretty -c
|
|
||||||
- xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK Framework" -sdk iphonesimulator
|
- xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK Framework" -sdk iphonesimulator
|
||||||
-configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" test |
|
-configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test |
|
||||||
|
xcpretty -c
|
||||||
|
- xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK" -sdk iphonesimulator
|
||||||
|
-configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test |
|
||||||
xcpretty -c
|
xcpretty -c
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|||||||
49
Classes/BITCrashCXXExceptionHandler.h
Normal file
49
Classes/BITCrashCXXExceptionHandler.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Author: Gwynne Raskind <gwraskin@microsoft.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 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>
|
||||||
|
#import "HockeyNullability.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const void * __nullable exception;
|
||||||
|
const char * __nullable exception_type_name;
|
||||||
|
const char * __nullable exception_message;
|
||||||
|
uint32_t exception_frames_count;
|
||||||
|
const uintptr_t * __nonnull exception_frames;
|
||||||
|
} BITCrashUncaughtCXXExceptionInfo;
|
||||||
|
|
||||||
|
typedef void (*BITCrashUncaughtCXXExceptionHandler)(
|
||||||
|
const BITCrashUncaughtCXXExceptionInfo * __nonnull info
|
||||||
|
);
|
||||||
|
|
||||||
|
@interface BITCrashUncaughtCXXExceptionHandlerManager : NSObject
|
||||||
|
|
||||||
|
+ (void)addCXXExceptionHandler:(nonnull BITCrashUncaughtCXXExceptionHandler)handler;
|
||||||
|
+ (void)removeCXXExceptionHandler:(nonnull BITCrashUncaughtCXXExceptionHandler)handler;
|
||||||
|
|
||||||
|
@end
|
||||||
150
Classes/BITCrashCXXExceptionHandler.mm
Normal file
150
Classes/BITCrashCXXExceptionHandler.mm
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Author: Gwynne Raskind <gwraskin@microsoft.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 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 "BITCrashCXXExceptionHandler.h"
|
||||||
|
#import <vector>
|
||||||
|
#import <cxxabi.h>
|
||||||
|
#import <exception>
|
||||||
|
#import <stdexcept>
|
||||||
|
#import <typeinfo>
|
||||||
|
#import <string>
|
||||||
|
#import <pthread.h>
|
||||||
|
#import <dlfcn.h>
|
||||||
|
#import <execinfo.h>
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
|
typedef std::vector<BITCrashUncaughtCXXExceptionHandler> BITCrashUncaughtCXXExceptionHandlerList;
|
||||||
|
|
||||||
|
static bool _BITCrashIsOurTerminateHandlerInstalled = false;
|
||||||
|
static std::terminate_handler _BITCrashOriginalTerminateHandler = nullptr;
|
||||||
|
static BITCrashUncaughtCXXExceptionHandlerList _BITCrashUncaughtExceptionHandlerList;
|
||||||
|
static OSSpinLock _BITCrashCXXExceptionHandlingLock = OS_SPINLOCK_INIT;
|
||||||
|
|
||||||
|
@implementation BITCrashUncaughtCXXExceptionHandlerManager
|
||||||
|
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void BITCrashIterateExceptionHandlers_unlocked(const BITCrashUncaughtCXXExceptionInfo &info)
|
||||||
|
{
|
||||||
|
for (const auto &handler : _BITCrashUncaughtExceptionHandlerList) {
|
||||||
|
handler(&info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BITCrashUncaughtCXXTerminateHandler(void)
|
||||||
|
{
|
||||||
|
BITCrashUncaughtCXXExceptionInfo info = {
|
||||||
|
.exception = nullptr,
|
||||||
|
.exception_type_name = nullptr,
|
||||||
|
.exception_message = nullptr,
|
||||||
|
.exception_frames_count = 0,
|
||||||
|
.exception_frames = nullptr,
|
||||||
|
};
|
||||||
|
auto p = std::current_exception();
|
||||||
|
|
||||||
|
OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); {
|
||||||
|
if (p) { // explicit operator bool
|
||||||
|
info.exception = reinterpret_cast<const void *>(&p);
|
||||||
|
info.exception_type_name = __cxxabiv1::__cxa_current_exception_type()->name();
|
||||||
|
|
||||||
|
void *frames[128] = { nullptr };
|
||||||
|
|
||||||
|
info.exception_frames_count = backtrace(&frames[0], sizeof(frames) / sizeof(frames[0])) - 1;
|
||||||
|
info.exception_frames = reinterpret_cast<uintptr_t *>(&frames[1]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(p);
|
||||||
|
} catch (const std::exception &e) { // C++ exception.
|
||||||
|
info.exception_message = e.what();
|
||||||
|
BITCrashIterateExceptionHandlers_unlocked(info);
|
||||||
|
} catch (const std::exception *e) { // C++ exception by pointer.
|
||||||
|
info.exception_message = e->what();
|
||||||
|
BITCrashIterateExceptionHandlers_unlocked(info);
|
||||||
|
} catch (const std::string &e) { // C++ string as exception.
|
||||||
|
info.exception_message = e.c_str();
|
||||||
|
BITCrashIterateExceptionHandlers_unlocked(info);
|
||||||
|
} catch (const std::string *e) { // C++ string pointer as exception.
|
||||||
|
info.exception_message = e->c_str();
|
||||||
|
BITCrashIterateExceptionHandlers_unlocked(info);
|
||||||
|
} catch (const char *e) { // Plain string as exception.
|
||||||
|
info.exception_message = e;
|
||||||
|
BITCrashIterateExceptionHandlers_unlocked(info);
|
||||||
|
} catch (id e) { // Objective-C exception. Pass it on to Foundation.
|
||||||
|
OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock);
|
||||||
|
if (_BITCrashOriginalTerminateHandler != nullptr) {
|
||||||
|
_BITCrashOriginalTerminateHandler();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} catch (...) { // Any other kind of exception. No message.
|
||||||
|
BITCrashIterateExceptionHandlers_unlocked(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); // In case terminate is called reentrantly by pasing it on
|
||||||
|
|
||||||
|
if (_BITCrashOriginalTerminateHandler != nullptr) {
|
||||||
|
_BITCrashOriginalTerminateHandler();
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)addCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler
|
||||||
|
{
|
||||||
|
OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); {
|
||||||
|
if (!_BITCrashIsOurTerminateHandlerInstalled) {
|
||||||
|
_BITCrashOriginalTerminateHandler = std::set_terminate(BITCrashUncaughtCXXTerminateHandler);
|
||||||
|
_BITCrashIsOurTerminateHandlerInstalled = true;
|
||||||
|
}
|
||||||
|
_BITCrashUncaughtExceptionHandlerList.push_back(handler);
|
||||||
|
} OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)removeCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler
|
||||||
|
{
|
||||||
|
OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); {
|
||||||
|
auto i = std::find(_BITCrashUncaughtExceptionHandlerList.begin(), _BITCrashUncaughtExceptionHandlerList.end(), handler);
|
||||||
|
|
||||||
|
if (i != _BITCrashUncaughtExceptionHandlerList.end()) {
|
||||||
|
_BITCrashUncaughtExceptionHandlerList.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_BITCrashIsOurTerminateHandlerInstalled) {
|
||||||
|
if (_BITCrashUncaughtExceptionHandlerList.empty()) {
|
||||||
|
std::terminate_handler previous_handler = std::set_terminate(_BITCrashOriginalTerminateHandler);
|
||||||
|
|
||||||
|
if (previous_handler != BITCrashUncaughtCXXTerminateHandler) {
|
||||||
|
std::set_terminate(previous_handler);
|
||||||
|
} else {
|
||||||
|
_BITCrashIsOurTerminateHandlerInstalled = false;
|
||||||
|
_BITCrashOriginalTerminateHandler = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -44,6 +44,7 @@
|
|||||||
#import "BITCrashManagerPrivate.h"
|
#import "BITCrashManagerPrivate.h"
|
||||||
#import "BITCrashReportTextFormatter.h"
|
#import "BITCrashReportTextFormatter.h"
|
||||||
#import "BITCrashDetailsPrivate.h"
|
#import "BITCrashDetailsPrivate.h"
|
||||||
|
#import "BITCrashCXXExceptionHandler.h"
|
||||||
|
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
@ -97,6 +98,63 @@ static PLCrashReporterCallbacks plCrashCallbacks = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Temporary class until PLCR catches up
|
||||||
|
// We trick PLCR with an Objective-C exception.
|
||||||
|
//
|
||||||
|
// This code provides us access to the C++ exception message, but we won't get a correct stack trace.
|
||||||
|
// The cause for this is that the iOS runtime catches every C++ exception internally and rethrows it.
|
||||||
|
// Since the exception object doesn't have the backtrace attached, we have no chance of accessing it.
|
||||||
|
//
|
||||||
|
// As a workaround we could hook into __cxx_throw and attaching the backtrace every time this is called.
|
||||||
|
// This has a few sides effects which is why we are not doing this right now:
|
||||||
|
// - CoreAdudio (and possibly other frameworks) use C++ exceptions heavily for control flow.
|
||||||
|
// Calling `backtrace()` is not cheap, so this could affect performance
|
||||||
|
// - It is not clear if such a hook is ABI compatible with all C++ runtimes
|
||||||
|
// - It is not clear if there could be any other side effects
|
||||||
|
//
|
||||||
|
// We'll evaluate this further to see if there is a safe solution.
|
||||||
|
//
|
||||||
|
@interface BITCrashCXXExceptionWrapperException : NSException
|
||||||
|
- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation BITCrashCXXExceptionWrapperException {
|
||||||
|
const BITCrashUncaughtCXXExceptionInfo *_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info {
|
||||||
|
extern char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status);
|
||||||
|
char *demangled_name = __cxa_demangle ? __cxa_demangle(info->exception_type_name ?: "", NULL, NULL, NULL) : NULL;
|
||||||
|
|
||||||
|
if ((self = [super
|
||||||
|
initWithName:[NSString stringWithUTF8String:demangled_name ?: info->exception_type_name ?: ""]
|
||||||
|
reason:[NSString stringWithUTF8String:info->exception_message ?: ""]
|
||||||
|
userInfo:nil])) {
|
||||||
|
_info = info;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)callStackReturnAddresses {
|
||||||
|
NSMutableArray *cxxFrames = [NSMutableArray arrayWithCapacity:_info->exception_frames_count];
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < _info->exception_frames_count; ++i) {
|
||||||
|
[cxxFrames addObject:[NSNumber numberWithUnsignedLongLong:_info->exception_frames[i]]];
|
||||||
|
}
|
||||||
|
return cxxFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
// C++ Exception Handler
|
||||||
|
static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInfo *info) {
|
||||||
|
// This relies on a LOT of sneaky internal knowledge of how PLCR works and should not be considered a long-term solution.
|
||||||
|
NSGetUncaughtExceptionHandler()([[BITCrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@implementation BITCrashManager {
|
@implementation BITCrashManager {
|
||||||
NSMutableDictionary *_approvedCrashReports;
|
NSMutableDictionary *_approvedCrashReports;
|
||||||
|
|
||||||
@ -1091,6 +1149,9 @@ static PLCrashReporterCallbacks plCrashCallbacks = {
|
|||||||
// this should never happen, theoretically only if NSSetUncaugtExceptionHandler() has some internal issues
|
// this should never happen, theoretically only if NSSetUncaugtExceptionHandler() has some internal issues
|
||||||
NSLog(@"[HockeySDK] ERROR: Exception handler could not be set. Make sure there is no other exception handler set up!");
|
NSLog(@"[HockeySDK] ERROR: Exception handler could not be set. Make sure there is no other exception handler set up!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the C++ uncaught exception handler, which is currently not handled by PLCrashReporter internally
|
||||||
|
[BITCrashUncaughtCXXExceptionHandlerManager addCXXExceptionHandler:uncaught_cxx_exception_handler];
|
||||||
}
|
}
|
||||||
_isSetup = YES;
|
_isSetup = YES;
|
||||||
});
|
});
|
||||||
|
|||||||
33
Classes/HockeyNullability.h
Normal file
33
Classes/HockeyNullability.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// HockeyNullability.h
|
||||||
|
// HockeySDK
|
||||||
|
//
|
||||||
|
// Created by Andreas Linde on 12/06/15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef HockeySDK_HockeyNullability_h
|
||||||
|
#define HockeySDK_HockeyNullability_h
|
||||||
|
|
||||||
|
// Define nullability fallback for backwards compatibility
|
||||||
|
#if !__has_feature(nullability)
|
||||||
|
#define NS_ASSUME_NONNULL_BEGIN
|
||||||
|
#define NS_ASSUME_NONNULL_END
|
||||||
|
#define nullable
|
||||||
|
#define nonnull
|
||||||
|
#define null_unspecified
|
||||||
|
#define null_resettable
|
||||||
|
#define __nullable
|
||||||
|
#define __nonnull
|
||||||
|
#define __null_unspecified
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fallback for convenience syntax which might not be available in older SDKs
|
||||||
|
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||||
|
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
|
||||||
|
#endif
|
||||||
|
#ifndef NS_ASSUME_NONNULL_END
|
||||||
|
#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -27,8 +27,6 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HockeySDK_h
|
|
||||||
#define HockeySDK_h
|
|
||||||
|
|
||||||
#import "HockeySDKFeatureConfig.h"
|
#import "HockeySDKFeatureConfig.h"
|
||||||
|
|
||||||
@ -208,5 +206,3 @@ typedef NS_ENUM(NSInteger, BITHockeyErrorReason) {
|
|||||||
};
|
};
|
||||||
extern NSString *const __attribute__((unused)) kBITHockeyErrorDomain;
|
extern NSString *const __attribute__((unused)) kBITHockeyErrorDomain;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ Pod::Spec.new do |s|
|
|||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
|
|
||||||
s.frameworks = 'AssetsLibrary', 'CoreText', 'CoreGraphics', 'MobileCoreServices', 'QuartzCore', 'QuickLook', 'Security', 'SystemConfiguration', 'UIKit'
|
s.frameworks = 'AssetsLibrary', 'CoreText', 'CoreGraphics', 'MobileCoreServices', 'QuartzCore', 'QuickLook', 'Security', 'SystemConfiguration', 'UIKit'
|
||||||
|
s.libraries = 'c++'
|
||||||
s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework'
|
s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework'
|
||||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"38\\"" BITHOCKEY_C_BUILD="\\"38\\""} }
|
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"38\\"" BITHOCKEY_C_BUILD="\\"38\\""} }
|
||||||
s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] }
|
s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] }
|
||||||
|
|||||||
@ -34,7 +34,6 @@ The main SDK class is `BITHockeyManager`. It initializes all modules and provide
|
|||||||
## Installation & Setup
|
## Installation & Setup
|
||||||
|
|
||||||
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/Guide-Installation-Setup.html) (Recommended)
|
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/Guide-Installation-Setup.html) (Recommended)
|
||||||
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.6.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.6.4/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
|
- [Identify and authenticate users of Ad-Hoc or Enterprise builds](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
|
||||||
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.6.2/docs/docs/Guide-Migration-Kits.html)
|
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.6.2/docs/docs/Guide-Migration-Kits.html)
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
OTHER_LDFLAGS=$(inherited) -framework CoreText -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -framework Security -framework AssetsLibrary -framework MobileCoreServices -framework QuickLook
|
OTHER_LDFLAGS=$(inherited) -framework CoreText -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -framework Security -framework AssetsLibrary -framework MobileCoreServices -framework QuickLook -lc++
|
||||||
HOCKEYSDK_DOCSET_NAME=HockeySDK-iOS
|
HOCKEYSDK_DOCSET_NAME=HockeySDK-iOS
|
||||||
GCC_PREPROCESSOR_DEFINITIONS=$(inherited) CONFIGURATION_$(CONFIGURATION)
|
GCC_PREPROCESSOR_DEFINITIONS=$(inherited) CONFIGURATION_$(CONFIGURATION)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -3,4 +3,16 @@ framework module HockeySDK {
|
|||||||
|
|
||||||
export *
|
export *
|
||||||
module * { export * }
|
module * { export * }
|
||||||
|
|
||||||
|
link framework "AssetsLibrary"
|
||||||
|
link framework "CoreText"
|
||||||
|
link framework "CoreGraphics"
|
||||||
|
link framework "Foundation"
|
||||||
|
link framework "MobileCoreServices"
|
||||||
|
link framework "QuartzCore"
|
||||||
|
link framework "QuickLook"
|
||||||
|
link framework "Security"
|
||||||
|
link framework "SystemConfiguration"
|
||||||
|
link framework "UIKit"
|
||||||
|
link "c++"
|
||||||
}
|
}
|
||||||
|
|||||||
12
Support/module_crashonly.modulemap
Normal file
12
Support/module_crashonly.modulemap
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
framework module HockeySDK {
|
||||||
|
umbrella header "HockeySDK.h"
|
||||||
|
|
||||||
|
export *
|
||||||
|
module * { export * }
|
||||||
|
|
||||||
|
link framework "Foundation"
|
||||||
|
link framework "Security"
|
||||||
|
link framework "SystemConfiguration"
|
||||||
|
link framework "UIKit"
|
||||||
|
link "c++"
|
||||||
|
}
|
||||||
@ -1,209 +0,0 @@
|
|||||||
## Version 3.6.4
|
|
||||||
|
|
||||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/Changelog.html)
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
This article describes how to integrate HockeyApp into your iOS apps using a Git submodule and Xcode sub-projects. The SDK allows testers to update your app to another beta version right from within the application. It will notify the tester if a new update is available. The SDK also allows to send crash reports. If a crash has happened, it will ask the tester on the next start whether he wants to send information about the crash to the server.
|
|
||||||
|
|
||||||
This document contains the following sections:
|
|
||||||
|
|
||||||
- [Requirements](#requirements)
|
|
||||||
- [Set up Git submodule](#download)
|
|
||||||
- [Set up Xcode](#xcode)
|
|
||||||
- [Modify Code](#modify)
|
|
||||||
- [iOS 8 Extensions](#extension)
|
|
||||||
- [Additional Options](#options)
|
|
||||||
|
|
||||||
<a id="requirements"></a>
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
The SDK runs on devices with iOS 6.0 or higher.
|
|
||||||
|
|
||||||
<a id="download"></a>
|
|
||||||
## Set up Git submodule
|
|
||||||
|
|
||||||
1. Open a Terminal window
|
|
||||||
|
|
||||||
2. Change to your projects directory `cd /path/to/MyProject'
|
|
||||||
|
|
||||||
3. If this is a new project, initialize Git: `git init`
|
|
||||||
|
|
||||||
4. Add the submodule: `git submodule add git://github.com/bitstadium/HockeySDK-iOS.git Vendor/HockeySDK`. This would add the submodule into the `Vendor/HockeySDK` subfolder. Change this to the folder you prefer.
|
|
||||||
|
|
||||||
5. Releases are always in the `master` branch while the `develop` branch provides the latest in development source code (Using the git flow branching concept). We recommend using the `master` branch!
|
|
||||||
|
|
||||||
<a id="xcode"></a>
|
|
||||||
## Set up Xcode
|
|
||||||
|
|
||||||
1. Find the `HockeySDK.xcodeproj` file inside of the cloned HockeySDK-iOS project directory.
|
|
||||||
|
|
||||||
2. Drag & Drop it into the `Project Navigator` (⌘+1).
|
|
||||||
|
|
||||||
3. Select your project in the `Project Navigator` (⌘+1).
|
|
||||||
|
|
||||||
4. Select your app target.
|
|
||||||
|
|
||||||
5. Select the tab `Build Phases`.
|
|
||||||
|
|
||||||
6. Expand `Link Binary With Libraries`.
|
|
||||||
|
|
||||||
7. Add `libHockeySDK.a`
|
|
||||||
|
|
||||||
<img src="XcodeLinkBinariesLib_normal.png"/>
|
|
||||||
|
|
||||||
8. Select `Add Other...`.
|
|
||||||
|
|
||||||
9. Select `CrashReporter.framework` from the `Vendor/HockeySDK/Vendor` folder
|
|
||||||
|
|
||||||
<img src="XcodeFrameworks4_normal.png"/>
|
|
||||||
|
|
||||||
10. Add the following system frameworks, if they are missing:
|
|
||||||
- `AssetsLibrary`
|
|
||||||
- `CoreText`
|
|
||||||
- `CoreGraphics`
|
|
||||||
- `Foundation`
|
|
||||||
- `MobileCoreServices`
|
|
||||||
- `QuartzCore`
|
|
||||||
- `QuickLook`
|
|
||||||
- `Security`
|
|
||||||
- `SystemConfiguration`
|
|
||||||
- `UIKit`
|
|
||||||
|
|
||||||
11. Expand `Copy Bundle Resource`.
|
|
||||||
|
|
||||||
12. Drag `HockeySDKResources.bundle` from the `HockeySDK` sub-projects `Products` folder and drop into the `Copy Bundle Resource` section
|
|
||||||
|
|
||||||
13. Select `Build Settings`
|
|
||||||
|
|
||||||
14. Add the following `Header Search Path`
|
|
||||||
|
|
||||||
`$(SRCROOT)/Vendor/HockeySDK/Classes`
|
|
||||||
|
|
||||||
<a id="modify"></a>
|
|
||||||
## Modify Code
|
|
||||||
|
|
||||||
### Objective-C
|
|
||||||
|
|
||||||
1. Open your `AppDelegate.m` file.
|
|
||||||
|
|
||||||
2. Add the following line at the top of the file below your own #import statements:
|
|
||||||
|
|
||||||
#import <HockeySDK/HockeySDK.h>
|
|
||||||
|
|
||||||
3. Search for the method `application:didFinishLaunchingWithOptions:`
|
|
||||||
|
|
||||||
4. Add the following lines:
|
|
||||||
|
|
||||||
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
|
|
||||||
[[BITHockeyManager sharedHockeyManager] startManager];
|
|
||||||
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
|
|
||||||
|
|
||||||
5. Continue with [General subsection](#generalcode)
|
|
||||||
|
|
||||||
### Swift
|
|
||||||
|
|
||||||
1. Add the following line to your [Objective-C bridging header](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html) file:
|
|
||||||
|
|
||||||
#import <HockeySDK/HockeySDK.h>
|
|
||||||
|
|
||||||
2. Open your `AppDelegate.swift` file.
|
|
||||||
|
|
||||||
3. Search for the method `application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool`
|
|
||||||
|
|
||||||
4. Add the following lines:
|
|
||||||
|
|
||||||
BITHockeyManager.sharedHockeyManager().configureWithIdentifier("APP_IDENTIFIER");
|
|
||||||
BITHockeyManager.sharedHockeyManager().startManager();
|
|
||||||
BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation();
|
|
||||||
|
|
||||||
5. Continue with [General subsection](#generalcode)
|
|
||||||
|
|
||||||
<a id="generalcode"></a>
|
|
||||||
### General
|
|
||||||
|
|
||||||
1. Replace `APP_IDENTIFIER` with the app identifier of your beta app. If you don't know what the app identifier is or how to find it, please read [this how-to](http://support.hockeyapp.net/kb/how-tos/how-to-find-the-app-identifier).
|
|
||||||
|
|
||||||
2. If you want to see beta analytics, use the beta distribution feature with in-app updates, restrict versions to specific users, or want to know who is actually testing your app, you need to follow the instructions on our guide [Identify and authenticate users of Ad-Hoc or Enterprise builds](HowTo-Authenticating-Users-on-iOS)
|
|
||||||
|
|
||||||
*Note:* The SDK is optimized to defer everything possible to a later time while making sure e.g. crashes on startup can also be caught and each module executes other code with a delay some seconds. This ensures that applicationDidFinishLaunching will process as fast as possible and the SDK will not block the startup sequence resulting in a possible kill by the watchdog process.
|
|
||||||
|
|
||||||
<a id="extensions"></a>
|
|
||||||
## iOS 8 Extensions
|
|
||||||
|
|
||||||
The following points need to be considered to use HockeySDK with iOS 8 Extensions:
|
|
||||||
|
|
||||||
1. Each extension is required to use the same values for version (`CFBundleShortVersionString`) and build number (`CFBundleVersion`) as the main app uses. (This is required only if you are using the same APP_IDENTIFIER for your app and extensions).
|
|
||||||
2. You need to make sure the SDK setup code is only invoked once. Since there is no `applicationDidFinishLaunching:` equivalent and `viewDidLoad` can run multiple times, you need to use a setup like the following example:
|
|
||||||
|
|
||||||
@interface TodayViewController () <NCWidgetProviding>
|
|
||||||
|
|
||||||
@property (nonatomic, assign) BOOL didSetupHockeySDK;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation TodayViewController
|
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
|
||||||
[super viewDidLoad];
|
|
||||||
if (!self.didSetupHockeySDK) {
|
|
||||||
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
|
|
||||||
[[BITHockeyManager sharedHockeyManager] startManager];
|
|
||||||
self.didSetupHockeySDK = YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<a id="options"></a>
|
|
||||||
## Additional Options
|
|
||||||
|
|
||||||
### Xcode Documentation
|
|
||||||
|
|
||||||
This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and how-tos.
|
|
||||||
|
|
||||||
1. Download the [HockeySDK-iOS documentation](http://hockeyapp.net/releases/).
|
|
||||||
|
|
||||||
2. Unzip the file. A new folder `HockeySDK-iOS-documentation` is created.
|
|
||||||
|
|
||||||
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.6.4/](http://hockeyapp.net/help/sdk/ios/3.6.4/)
|
|
||||||
|
|
||||||
### Set up with xcconfig
|
|
||||||
|
|
||||||
Instead of manually adding the missing frameworks, you can also use our bundled xcconfig file.
|
|
||||||
|
|
||||||
1. Create a new `Project.xcconfig` file, if you don't already have one (You can give it any name)
|
|
||||||
|
|
||||||
**Note:** You can also add the required frameworks manually to your targets `Build Phases` an continue with step `4.` instead.
|
|
||||||
|
|
||||||
a. Select your project in the `Project Navigator` (⌘+1).
|
|
||||||
|
|
||||||
b. Select the tab `Info`.
|
|
||||||
|
|
||||||
c. Expand `Configurations`.
|
|
||||||
|
|
||||||
d. Select `Project.xcconfig` for all your configurations
|
|
||||||
|
|
||||||
<img src="XcodeFrameworks1_normal.png"/>
|
|
||||||
|
|
||||||
2. Open `Project.xcconfig` in the editor
|
|
||||||
|
|
||||||
3. Add the following line:
|
|
||||||
|
|
||||||
`#include "../Vendor/HockeySDK/Support/HockeySDK.xcconfig"`
|
|
||||||
|
|
||||||
(Adjust the path depending where the `Project.xcconfig` file is located related to the Xcode project package)
|
|
||||||
|
|
||||||
**Important note:** Check if you overwrite any of the build settings and add a missing `$(inherited)` entry on the projects build settings level, so the `HockeySDK.xcconfig` settings will be passed through successfully.
|
|
||||||
|
|
||||||
4. If you are getting build warnings, then the `.xcconfig` setting wasn't included successfully or its settings in `Other Linker Flags` get ignored because `$(inherited)` is missing on project or target level. Either add `$(inherited)` or link the following frameworks manually in `Link Binary With Libraries` under `Build Phases`:
|
|
||||||
- `AssetsLibrary`
|
|
||||||
- `CoreText`
|
|
||||||
- `CoreGraphics`
|
|
||||||
- `Foundation`
|
|
||||||
- `MobileCoreServices`
|
|
||||||
- `QuartzCore`
|
|
||||||
- `QuickLook`
|
|
||||||
- `Security`
|
|
||||||
- `SystemConfiguration`
|
|
||||||
- `UIKit`
|
|
||||||
@ -32,6 +32,8 @@ The SDK runs on devices with iOS 6.0 or higher.
|
|||||||
<a id="xcode"></a>
|
<a id="xcode"></a>
|
||||||
## Set up Xcode
|
## Set up Xcode
|
||||||
|
|
||||||
|
### Full featured SDK
|
||||||
|
|
||||||
1. Drag & drop `HockeySDK.embeddedframework` from your project directory to your Xcode project.
|
1. Drag & drop `HockeySDK.embeddedframework` from your project directory to your Xcode project.
|
||||||
|
|
||||||
2. Similar to above, our projects have a group `Vendor`, so we drop it there.
|
2. Similar to above, our projects have a group `Vendor`, so we drop it there.
|
||||||
@ -42,13 +44,15 @@ The SDK runs on devices with iOS 6.0 or higher.
|
|||||||
|
|
||||||
4. Select your project in the `Project Navigator` (⌘+1).
|
4. Select your project in the `Project Navigator` (⌘+1).
|
||||||
|
|
||||||
5. Select your app target.
|
5. If your app target is enabled to use Modules (which is default since Xcode 5 for new projects), you can continue with the section "Modify Code", otherwise continue with step 6.
|
||||||
|
|
||||||
6. Select the tab `Build Phases`.
|
6. Select your app target.
|
||||||
|
|
||||||
7. Expand `Link Binary With Libraries`.
|
7. Select the tab `Build Phases`.
|
||||||
|
|
||||||
8. Add the following system frameworks, if they are missing:
|
8. Expand `Link Binary With Libraries`.
|
||||||
|
|
||||||
|
9. Add the following system frameworks, if they are missing:
|
||||||
- `AssetsLibrary`
|
- `AssetsLibrary`
|
||||||
- `CoreText`
|
- `CoreText`
|
||||||
- `CoreGraphics`
|
- `CoreGraphics`
|
||||||
@ -59,6 +63,35 @@ The SDK runs on devices with iOS 6.0 or higher.
|
|||||||
- `Security`
|
- `Security`
|
||||||
- `SystemConfiguration`
|
- `SystemConfiguration`
|
||||||
- `UIKit`
|
- `UIKit`
|
||||||
|
- `libc++`
|
||||||
|
|
||||||
|
### Crash reporting only SDK
|
||||||
|
|
||||||
|
1. Drag & drop `HockeySDK.framework` from your project directory to your Xcode project.
|
||||||
|
|
||||||
|
2. If you don't want to auto-send crash reports, also copy the following resource bundle from `HockeySDK.embeddedframework/HockeySDK.framework/Versions/A/Resources/HockeySDKResources.bundle` into the same folder and Drag & drop it into your Xcode project
|
||||||
|
|
||||||
|
2. Similar to above, our projects have a group `Vendor`, so we drop it there.
|
||||||
|
|
||||||
|
3. Select `Create groups for any added folders` and set the checkmark for your target. Then click `Finish`.
|
||||||
|
|
||||||
|
<img src="XcodeCreateGroups_normal.png"/>
|
||||||
|
|
||||||
|
4. Select your project in the `Project Navigator` (⌘+1).
|
||||||
|
|
||||||
|
5. If your app target is enabled to use Modules (which is default since Xcode 5 for new projects), you can continue with the section "Modify Code", otherwise continue with step 6.
|
||||||
|
|
||||||
|
6. Select your app target.
|
||||||
|
|
||||||
|
7. Select the tab `Build Phases`.
|
||||||
|
|
||||||
|
8. Expand `Link Binary With Libraries`.
|
||||||
|
|
||||||
|
9. Add the following system frameworks, if they are missing (if you are using the full featured SDK):
|
||||||
|
- `Foundation`
|
||||||
|
- `Security`
|
||||||
|
- `SystemConfiguration`
|
||||||
|
- `UIKit`
|
||||||
|
|
||||||
<a id="modify"></a>
|
<a id="modify"></a>
|
||||||
## Modify Code
|
## Modify Code
|
||||||
@ -69,6 +102,12 @@ The SDK runs on devices with iOS 6.0 or higher.
|
|||||||
|
|
||||||
2. Add the following line at the top of the file below your own #import statements:
|
2. Add the following line at the top of the file below your own #import statements:
|
||||||
|
|
||||||
|
If your app target is enabled to use Modules (which is default since Xcode 5 for new projects) use:
|
||||||
|
|
||||||
|
@import HockeySDK
|
||||||
|
|
||||||
|
Otherwise use:
|
||||||
|
|
||||||
#import <HockeySDK/HockeySDK.h>
|
#import <HockeySDK/HockeySDK.h>
|
||||||
|
|
||||||
3. Search for the method `application:didFinishLaunchingWithOptions:`
|
3. Search for the method `application:didFinishLaunchingWithOptions:`
|
||||||
@ -77,7 +116,7 @@ The SDK runs on devices with iOS 6.0 or higher.
|
|||||||
|
|
||||||
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
|
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
|
||||||
[[BITHockeyManager sharedHockeyManager] startManager];
|
[[BITHockeyManager sharedHockeyManager] startManager];
|
||||||
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
|
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; // This line is obsolete in the crash only build
|
||||||
|
|
||||||
5. Continue with [General subsection](#generalcode)
|
5. Continue with [General subsection](#generalcode)
|
||||||
|
|
||||||
@ -95,7 +134,7 @@ The SDK runs on devices with iOS 6.0 or higher.
|
|||||||
|
|
||||||
BITHockeyManager.sharedHockeyManager().configureWithIdentifier("APP_IDENTIFIER");
|
BITHockeyManager.sharedHockeyManager().configureWithIdentifier("APP_IDENTIFIER");
|
||||||
BITHockeyManager.sharedHockeyManager().startManager();
|
BITHockeyManager.sharedHockeyManager().startManager();
|
||||||
BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation();
|
BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation(); // This line is obsolete in the crash only build
|
||||||
|
|
||||||
5. Continue with [General subsection](#generalcode)
|
5. Continue with [General subsection](#generalcode)
|
||||||
|
|
||||||
@ -183,3 +222,4 @@ Instead of manually adding the missing frameworks, you can also use our bundled
|
|||||||
- `Security`
|
- `Security`
|
||||||
- `SystemConfiguration`
|
- `SystemConfiguration`
|
||||||
- `UIKit`
|
- `UIKit`
|
||||||
|
- `libc++`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user