Merge pull request #167 from bitstadium/feature/cxx-exception-support

Add C++ Exception support
This commit is contained in:
Andreas Linde 2015-06-12 16:52:03 +02:00
commit 12e6f7bf67
14 changed files with 405 additions and 239 deletions

View File

@ -4,10 +4,10 @@ before_install:
script:
- set -o pipefail
- 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
-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
- cd ..

View 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

View 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

View File

@ -44,6 +44,7 @@
#import "BITCrashManagerPrivate.h"
#import "BITCrashReportTextFormatter.h"
#import "BITCrashDetailsPrivate.h"
#import "BITCrashCXXExceptionHandler.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 {
NSMutableDictionary *_approvedCrashReports;
@ -1091,6 +1149,9 @@ static PLCrashReporterCallbacks plCrashCallbacks = {
// 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!");
}
// Add the C++ uncaught exception handler, which is currently not handled by PLCrashReporter internally
[BITCrashUncaughtCXXExceptionHandlerManager addCXXExceptionHandler:uncaught_cxx_exception_handler];
}
_isSetup = YES;
});

View 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

View File

@ -27,8 +27,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef HockeySDK_h
#define HockeySDK_h
#import "HockeySDKFeatureConfig.h"
@ -208,5 +206,3 @@ typedef NS_ENUM(NSInteger, BITHockeyErrorReason) {
};
extern NSString *const __attribute__((unused)) kBITHockeyErrorDomain;
#endif

View File

@ -23,6 +23,7 @@ Pod::Spec.new do |s|
s.requires_arc = true
s.frameworks = 'AssetsLibrary', 'CoreText', 'CoreGraphics', 'MobileCoreServices', 'QuartzCore', 'QuickLook', 'Security', 'SystemConfiguration', 'UIKit'
s.libraries = 'c++'
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.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] }

View File

@ -34,7 +34,6 @@ The main SDK class is `BITHockeyManager`. It initializes all modules and provide
## Installation & Setup
- [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)
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.6.2/docs/docs/Guide-Migration-Kits.html)

View File

@ -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
GCC_PREPROCESSOR_DEFINITIONS=$(inherited) CONFIGURATION_$(CONFIGURATION)

File diff suppressed because one or more lines are too long

View File

@ -3,4 +3,16 @@ framework module HockeySDK {
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++"
}

View 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++"
}

View File

@ -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`

View File

@ -32,6 +32,8 @@ The SDK runs on devices with iOS 6.0 or higher.
<a id="xcode"></a>
## Set up Xcode
### Full featured SDK
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.
@ -42,13 +44,15 @@ The SDK runs on devices with iOS 6.0 or higher.
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`
- `CoreText`
- `CoreGraphics`
@ -59,6 +63,35 @@ The SDK runs on devices with iOS 6.0 or higher.
- `Security`
- `SystemConfiguration`
- `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>
## 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:
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>
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] startManager];
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; // This line is obsolete in the crash only build
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().startManager();
BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation();
BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation(); // This line is obsolete in the crash only build
5. Continue with [General subsection](#generalcode)
@ -183,3 +222,4 @@ Instead of manually adding the missing frameworks, you can also use our bundled
- `Security`
- `SystemConfiguration`
- `UIKit`
- `libc++`