├── .gitignore ├── .swift-version ├── ANREye.podspec ├── ANREye └── Classes │ ├── ANREye.swift │ └── Backtrace │ ├── AppBacktrace.swift │ ├── BSBacktraceLogger.h │ └── BSBacktraceLogger.m ├── Example ├── ANREye.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── ANREye.xcscmblueprint │ └── xcshareddata │ │ └── xcschemes │ │ ├── ANREye-Example.xcscheme │ │ └── ANREye.xcscheme ├── ANREye.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── ANREye.xcscmblueprint ├── ANREye │ ├── ANREye.h │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── ViewController.swift ├── Podfile ├── Podfile.lock └── Tests │ ├── Info.plist │ └── Tests.swift ├── LICENSE ├── README.md └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /ANREye.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint ANREye.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'ANREye' 11 | s.version = '1.2.0' 12 | s.summary = 'Class for monitor excessive blocking on the main thread.' 13 | 14 | s.description = <<-DESC 15 | Class for monitor excessive blocking on the main thread and return the stacetrace of all threads. 16 | DESC 17 | 18 | s.homepage = 'https://github.com/zixun/ANREye' 19 | s.license = { :type => 'MIT', :file => 'LICENSE' } 20 | s.author = { 'zixun' => 'chenyl.exe@gmail.com' } 21 | s.source = { :git => 'https://github.com/zixun/ANREye.git', :tag => s.version.to_s } 22 | s.social_media_url = 'https://twitter.com/zixun_' 23 | 24 | s.ios.deployment_target = '8.0' 25 | s.source_files = 'ANREye/Classes/**/*' 26 | end 27 | -------------------------------------------------------------------------------- /ANREye/Classes/ANREye.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ANREye.swift 3 | // Pods 4 | // 5 | // Created by zixun on 16/12/24. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | //-------------------------------------------------------------------------- 12 | // MARK: - ANREyeDelegate 13 | //-------------------------------------------------------------------------- 14 | @objc public protocol ANREyeDelegate: class { 15 | @objc optional func anrEye(anrEye:ANREye, 16 | catchWithThreshold threshold:Double, 17 | mainThreadBacktrace:String?, 18 | allThreadBacktrace:String?) 19 | } 20 | 21 | //-------------------------------------------------------------------------- 22 | // MARK: - ANREye 23 | //-------------------------------------------------------------------------- 24 | open class ANREye: NSObject { 25 | 26 | //-------------------------------------------------------------------------- 27 | // MARK: OPEN PROPERTY 28 | //-------------------------------------------------------------------------- 29 | open weak var delegate: ANREyeDelegate? 30 | 31 | open var isOpening: Bool { 32 | get { 33 | guard let pingThread = self.pingThread else { 34 | return false 35 | } 36 | return !pingThread.isCancelled 37 | } 38 | } 39 | //-------------------------------------------------------------------------- 40 | // MARK: OPEN FUNCTION 41 | //-------------------------------------------------------------------------- 42 | 43 | open func open(with threshold:Double) { 44 | if Thread.current.isMainThread { 45 | AppBacktrace.main_thread_id = mach_thread_self() 46 | }else { 47 | DispatchQueue.main.async { 48 | AppBacktrace.main_thread_id = mach_thread_self() 49 | } 50 | } 51 | 52 | self.pingThread = AppPingThread() 53 | self.pingThread?.start(threshold: threshold, handler: { [weak self] in 54 | guard let sself = self else { 55 | return 56 | } 57 | 58 | let main = AppBacktrace.mainThread() 59 | let all = AppBacktrace.allThread() 60 | sself.delegate?.anrEye?(anrEye: sself, 61 | catchWithThreshold: threshold, 62 | mainThreadBacktrace: main, 63 | allThreadBacktrace: all) 64 | 65 | }) 66 | } 67 | 68 | open func close() { 69 | self.pingThread?.cancel() 70 | } 71 | 72 | //-------------------------------------------------------------------------- 73 | // MARK: LIFE CYCLE 74 | //-------------------------------------------------------------------------- 75 | deinit { 76 | self.pingThread?.cancel() 77 | } 78 | 79 | //-------------------------------------------------------------------------- 80 | // MARK: PRIVATE PROPERTY 81 | //-------------------------------------------------------------------------- 82 | private var pingThread: AppPingThread? 83 | 84 | } 85 | 86 | //-------------------------------------------------------------------------- 87 | // MARK: - GLOBAL DEFINE 88 | //-------------------------------------------------------------------------- 89 | public typealias AppPingThreadCallBack = () -> Void 90 | 91 | //-------------------------------------------------------------------------- 92 | // MARK: - AppPingThread 93 | //-------------------------------------------------------------------------- 94 | private class AppPingThread: Thread { 95 | 96 | func start(threshold:Double, handler: @escaping AppPingThreadCallBack) { 97 | self.handler = handler 98 | self.threshold = threshold 99 | self.start() 100 | } 101 | 102 | override func main() { 103 | 104 | while self.isCancelled == false { 105 | self.isMainThreadBlock = true 106 | DispatchQueue.main.async { 107 | self.isMainThreadBlock = false 108 | self.semaphore.signal() 109 | } 110 | 111 | Thread.sleep(forTimeInterval: self.threshold) 112 | if self.isMainThreadBlock { 113 | self.handler?() 114 | } 115 | 116 | _ = self.semaphore.wait(timeout: DispatchTime.distantFuture) 117 | } 118 | } 119 | 120 | private let semaphore = DispatchSemaphore(value: 0) 121 | 122 | private var isMainThreadBlock = false 123 | 124 | private var threshold: Double = 0.4 125 | 126 | fileprivate var handler: (() -> Void)? 127 | } 128 | -------------------------------------------------------------------------------- /ANREye/Classes/Backtrace/AppBacktrace.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppBacktrace.swift 3 | // Pods 4 | // 5 | // Created by zixun on 16/12/19. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | class AppBacktrace: NSObject { 12 | 13 | 14 | class func with(thread: Thread) -> String { 15 | let machThread = self.bs_machThread(from: thread) 16 | return BSBacktraceLogger.backtrace(ofMachthread: machThread) 17 | } 18 | 19 | class func currentThread() -> String { 20 | return self.with(thread: Thread.current) 21 | } 22 | 23 | class func mainThread() -> String { 24 | return self.with(thread: Thread.main) 25 | } 26 | 27 | class func allThread() -> String { 28 | 29 | var threads: thread_act_array_t? = nil 30 | var thread_count = mach_msg_type_number_t() 31 | 32 | if task_threads(mach_task_self_, &(threads), &thread_count) != KERN_SUCCESS { 33 | return "" 34 | } 35 | 36 | var resultString = "Call Backtrace of \(thread_count) threads:\n" 37 | 38 | for i in 0.. thread_t { 53 | 54 | var name:[Int8] = Array(repeating:0, count:256) 55 | 56 | var list: thread_act_array_t? = nil 57 | var count = mach_msg_type_number_t() 58 | 59 | if task_threads(mach_task_self_, &(list), &count) != KERN_SUCCESS { 60 | return mach_thread_self() 61 | } 62 | 63 | let currentTimestamp = NSDate().timeIntervalSince1970 64 | let originName = nsthread.name 65 | nsthread.name = "\(currentTimestamp)" 66 | 67 | if nsthread.isMainThread { 68 | return self.main_thread_id 69 | } 70 | 71 | for i in 0.. 10 | 11 | #import 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | @interface BSBacktraceLogger : NSObject 21 | 22 | + (NSString *)backtraceOfMachthread:(thread_t)thread; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ANREye/Classes/Backtrace/BSBacktraceLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // BSBacktraceLogger.m 3 | // BSBacktraceLogger 4 | // 5 | // Created by 张星宇 on 16/8/27. 6 | // Copyright © 2016年 bestswifter. All rights reserved. 7 | // 8 | 9 | // Modified from https://github.com/bestswifter/BSBacktraceLogger 10 | // I dont know how to use _STRUCT_MCONTEXT in swift, so this code is still in objective-c 11 | // if you know it, please tell me at http://stackoverflow.com/questions/41314775/how-to-use-struct-mcontext-in-swift 12 | 13 | #import "BSBacktraceLogger.h" 14 | #import 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #pragma -mark DEFINE MACRO FOR DIFFERENT CPU ARCHITECTURE 24 | #if defined(__arm64__) 25 | #define DETAG_INSTRUCTION_ADDRESS(A) ((A) & ~(3UL)) 26 | #define BS_THREAD_STATE_COUNT ARM_THREAD_STATE64_COUNT 27 | #define BS_THREAD_STATE ARM_THREAD_STATE64 28 | #define BS_FRAME_POINTER __fp 29 | #define BS_STACK_POINTER __sp 30 | #define BS_INSTRUCTION_ADDRESS __pc 31 | 32 | #elif defined(__arm__) 33 | #define DETAG_INSTRUCTION_ADDRESS(A) ((A) & ~(1UL)) 34 | #define BS_THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT 35 | #define BS_THREAD_STATE ARM_THREAD_STATE 36 | #define BS_FRAME_POINTER __r[7] 37 | #define BS_STACK_POINTER __sp 38 | #define BS_INSTRUCTION_ADDRESS __pc 39 | 40 | #elif defined(__x86_64__) 41 | #define DETAG_INSTRUCTION_ADDRESS(A) (A) 42 | #define BS_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT 43 | #define BS_THREAD_STATE x86_THREAD_STATE64 44 | #define BS_FRAME_POINTER __rbp 45 | #define BS_STACK_POINTER __rsp 46 | #define BS_INSTRUCTION_ADDRESS __rip 47 | 48 | #elif defined(__i386__) 49 | #define DETAG_INSTRUCTION_ADDRESS(A) (A) 50 | #define BS_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT 51 | #define BS_THREAD_STATE x86_THREAD_STATE32 52 | #define BS_FRAME_POINTER __ebp 53 | #define BS_STACK_POINTER __esp 54 | #define BS_INSTRUCTION_ADDRESS __eip 55 | 56 | #endif 57 | 58 | #define CALL_INSTRUCTION_FROM_RETURN_ADDRESS(A) (DETAG_INSTRUCTION_ADDRESS((A)) - 1) 59 | 60 | #if defined(__LP64__) 61 | #define TRACE_FMT "%-4d%-31s 0x%016lx %s + %lu" 62 | #define POINTER_FMT "0x%016lx" 63 | #define POINTER_SHORT_FMT "0x%lx" 64 | #define BS_NLIST struct nlist_64 65 | #else 66 | #define TRACE_FMT "%-4d%-31s 0x%08lx %s + %lu" 67 | #define POINTER_FMT "0x%08lx" 68 | #define POINTER_SHORT_FMT "0x%lx" 69 | #define BS_NLIST struct nlist 70 | #endif 71 | 72 | 73 | typedef struct BSStackFrameEntry{ 74 | const struct BSStackFrameEntry *const previous; 75 | const uintptr_t return_address; 76 | } BSStackFrameEntry; 77 | 78 | @implementation BSBacktraceLogger 79 | 80 | + (NSString *)backtraceOfMachthread:(thread_t)thread { 81 | return _bs_backtraceOfThread(thread); 82 | } 83 | 84 | #pragma -mark Get call backtrace of a mach_thread 85 | NSString *_bs_backtraceOfThread(thread_t thread) { 86 | uintptr_t backtraceBuffer[50]; 87 | int i = 0; 88 | NSMutableString *resultString = [[NSMutableString alloc] initWithFormat:@"Backtrace of Thread %u:\n", thread]; 89 | 90 | _STRUCT_MCONTEXT machineContext; 91 | if(!bs_fillThreadStateIntoMachineContext(thread, &machineContext)) { 92 | return [NSString stringWithFormat:@"Fail to get information about thread: %u", thread]; 93 | } 94 | 95 | const uintptr_t instructionAddress = bs_mach_instructionAddress(&machineContext); 96 | backtraceBuffer[i] = instructionAddress; 97 | ++i; 98 | 99 | uintptr_t linkRegister = bs_mach_linkRegister(&machineContext); 100 | if (linkRegister) { 101 | backtraceBuffer[i] = linkRegister; 102 | i++; 103 | } 104 | 105 | if(instructionAddress == 0) { 106 | return @"Fail to get instruction address"; 107 | } 108 | 109 | BSStackFrameEntry frame = {0}; 110 | const uintptr_t framePtr = bs_mach_framePointer(&machineContext); 111 | if(framePtr == 0 || 112 | bs_mach_copyMem((void *)framePtr, &frame, sizeof(frame)) != KERN_SUCCESS) { 113 | return @"Fail to get frame pointer"; 114 | } 115 | 116 | for(; i < 50; i++) { 117 | backtraceBuffer[i] = frame.return_address; 118 | if(backtraceBuffer[i] == 0 || 119 | frame.previous == 0 || 120 | bs_mach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS) { 121 | break; 122 | } 123 | } 124 | 125 | int backtraceLength = i; 126 | Dl_info symbolicated[backtraceLength]; 127 | bs_symbolicate(backtraceBuffer, symbolicated, backtraceLength, 0); 128 | for (int i = 0; i < backtraceLength; ++i) { 129 | [resultString appendFormat:@"%@", bs_logBacktraceEntry(i, backtraceBuffer[i], &symbolicated[i])]; 130 | } 131 | [resultString appendFormat:@"\n"]; 132 | return [resultString copy]; 133 | } 134 | 135 | #pragma -mark GenerateBacbsrackEnrty 136 | NSString* bs_logBacktraceEntry(const int entryNum, 137 | const uintptr_t address, 138 | const Dl_info* const dlInfo) { 139 | char faddrBuff[20]; 140 | char saddrBuff[20]; 141 | 142 | const char* fname = bs_lastPathEntry(dlInfo->dli_fname); 143 | if(fname == NULL) { 144 | sprintf(faddrBuff, POINTER_FMT, (uintptr_t)dlInfo->dli_fbase); 145 | fname = faddrBuff; 146 | } 147 | 148 | uintptr_t offset = address - (uintptr_t)dlInfo->dli_saddr; 149 | const char* sname = dlInfo->dli_sname; 150 | if(sname == NULL) { 151 | sprintf(saddrBuff, POINTER_SHORT_FMT, (uintptr_t)dlInfo->dli_fbase); 152 | sname = saddrBuff; 153 | offset = address - (uintptr_t)dlInfo->dli_fbase; 154 | } 155 | return [NSString stringWithFormat:@"%-30s 0x%08" PRIxPTR " %s + %lu\n" ,fname, (uintptr_t)address, sname, offset]; 156 | } 157 | 158 | const char* bs_lastPathEntry(const char* const path) { 159 | if(path == NULL) { 160 | return NULL; 161 | } 162 | 163 | char* lastFile = strrchr(path, '/'); 164 | return lastFile == NULL ? path : lastFile + 1; 165 | } 166 | 167 | #pragma -mark HandleMachineContext 168 | bool bs_fillThreadStateIntoMachineContext(thread_t thread, _STRUCT_MCONTEXT *machineContext) { 169 | mach_msg_type_number_t state_count = BS_THREAD_STATE_COUNT; 170 | kern_return_t kr = thread_get_state(thread, BS_THREAD_STATE, (thread_state_t)&machineContext->__ss, &state_count); 171 | return (kr == KERN_SUCCESS); 172 | } 173 | 174 | uintptr_t bs_mach_framePointer(mcontext_t const machineContext){ 175 | return machineContext->__ss.BS_FRAME_POINTER; 176 | } 177 | 178 | uintptr_t bs_mach_stackPointer(mcontext_t const machineContext){ 179 | return machineContext->__ss.BS_STACK_POINTER; 180 | } 181 | 182 | uintptr_t bs_mach_instructionAddress(mcontext_t const machineContext){ 183 | return machineContext->__ss.BS_INSTRUCTION_ADDRESS; 184 | } 185 | 186 | uintptr_t bs_mach_linkRegister(mcontext_t const machineContext){ 187 | #if defined(__i386__) || defined(__x86_64__) 188 | return 0; 189 | #else 190 | return machineContext->__ss.__lr; 191 | #endif 192 | } 193 | 194 | kern_return_t bs_mach_copyMem(const void *const src, void *const dst, const size_t numBytes){ 195 | vm_size_t bytesCopied = 0; 196 | return vm_read_overwrite(mach_task_self(), (vm_address_t)src, (vm_size_t)numBytes, (vm_address_t)dst, &bytesCopied); 197 | } 198 | 199 | #pragma -mark Symbolicate 200 | void bs_symbolicate(const uintptr_t* const backtraceBuffer, 201 | Dl_info* const symbolsBuffer, 202 | const int numEntries, 203 | const int skippedEntries){ 204 | int i = 0; 205 | 206 | if(!skippedEntries && i < numEntries) { 207 | bs_dladdr(backtraceBuffer[i], &symbolsBuffer[i]); 208 | i++; 209 | } 210 | 211 | for(; i < numEntries; i++) { 212 | bs_dladdr(CALL_INSTRUCTION_FROM_RETURN_ADDRESS(backtraceBuffer[i]), &symbolsBuffer[i]); 213 | } 214 | } 215 | 216 | bool bs_dladdr(const uintptr_t address, Dl_info* const info) { 217 | info->dli_fname = NULL; 218 | info->dli_fbase = NULL; 219 | info->dli_sname = NULL; 220 | info->dli_saddr = NULL; 221 | 222 | const uint32_t idx = bs_imageIndexContainingAddress(address); 223 | if(idx == UINT_MAX) { 224 | return false; 225 | } 226 | const struct mach_header* header = _dyld_get_image_header(idx); 227 | const uintptr_t imageVMAddrSlide = (uintptr_t)_dyld_get_image_vmaddr_slide(idx); 228 | const uintptr_t addressWithSlide = address - imageVMAddrSlide; 229 | const uintptr_t segmentBase = bs_segmentBaseOfImageIndex(idx) + imageVMAddrSlide; 230 | if(segmentBase == 0) { 231 | return false; 232 | } 233 | 234 | info->dli_fname = _dyld_get_image_name(idx); 235 | info->dli_fbase = (void*)header; 236 | 237 | // Find symbol tables and get whichever symbol is closest to the address. 238 | const BS_NLIST* bestMatch = NULL; 239 | uintptr_t bestDistance = ULONG_MAX; 240 | uintptr_t cmdPtr = bs_firstCmdAfterHeader(header); 241 | if(cmdPtr == 0) { 242 | return false; 243 | } 244 | for(uint32_t iCmd = 0; iCmd < header->ncmds; iCmd++) { 245 | const struct load_command* loadCmd = (struct load_command*)cmdPtr; 246 | if(loadCmd->cmd == LC_SYMTAB) { 247 | const struct symtab_command* symtabCmd = (struct symtab_command*)cmdPtr; 248 | const BS_NLIST* symbolTable = (BS_NLIST*)(segmentBase + symtabCmd->symoff); 249 | const uintptr_t stringTable = segmentBase + symtabCmd->stroff; 250 | 251 | for(uint32_t iSym = 0; iSym < symtabCmd->nsyms; iSym++) { 252 | // If n_value is 0, the symbol refers to an external object. 253 | if(symbolTable[iSym].n_value != 0) { 254 | uintptr_t symbolBase = symbolTable[iSym].n_value; 255 | uintptr_t currentDistance = addressWithSlide - symbolBase; 256 | if((addressWithSlide >= symbolBase) && 257 | (currentDistance <= bestDistance)) { 258 | bestMatch = symbolTable + iSym; 259 | bestDistance = currentDistance; 260 | } 261 | } 262 | } 263 | if(bestMatch != NULL) { 264 | info->dli_saddr = (void*)(bestMatch->n_value + imageVMAddrSlide); 265 | info->dli_sname = (char*)((intptr_t)stringTable + (intptr_t)bestMatch->n_un.n_strx); 266 | if(*info->dli_sname == '_') { 267 | info->dli_sname++; 268 | } 269 | // This happens if all symbols have been stripped. 270 | if(info->dli_saddr == info->dli_fbase && bestMatch->n_type == 3) { 271 | info->dli_sname = NULL; 272 | } 273 | break; 274 | } 275 | } 276 | cmdPtr += loadCmd->cmdsize; 277 | } 278 | return true; 279 | } 280 | 281 | uintptr_t bs_firstCmdAfterHeader(const struct mach_header* const header) { 282 | switch(header->magic) { 283 | case MH_MAGIC: 284 | case MH_CIGAM: 285 | return (uintptr_t)(header + 1); 286 | case MH_MAGIC_64: 287 | case MH_CIGAM_64: 288 | return (uintptr_t)(((struct mach_header_64*)header) + 1); 289 | default: 290 | return 0; // Header is corrupt 291 | } 292 | } 293 | 294 | uint32_t bs_imageIndexContainingAddress(const uintptr_t address) { 295 | const uint32_t imageCount = _dyld_image_count(); 296 | const struct mach_header* header = 0; 297 | 298 | for(uint32_t iImg = 0; iImg < imageCount; iImg++) { 299 | header = _dyld_get_image_header(iImg); 300 | if(header != NULL) { 301 | // Look for a segment command with this address within its range. 302 | uintptr_t addressWSlide = address - (uintptr_t)_dyld_get_image_vmaddr_slide(iImg); 303 | uintptr_t cmdPtr = bs_firstCmdAfterHeader(header); 304 | if(cmdPtr == 0) { 305 | continue; 306 | } 307 | for(uint32_t iCmd = 0; iCmd < header->ncmds; iCmd++) { 308 | const struct load_command* loadCmd = (struct load_command*)cmdPtr; 309 | if(loadCmd->cmd == LC_SEGMENT) { 310 | const struct segment_command* segCmd = (struct segment_command*)cmdPtr; 311 | if(addressWSlide >= segCmd->vmaddr && 312 | addressWSlide < segCmd->vmaddr + segCmd->vmsize) { 313 | return iImg; 314 | } 315 | } 316 | else if(loadCmd->cmd == LC_SEGMENT_64) { 317 | const struct segment_command_64* segCmd = (struct segment_command_64*)cmdPtr; 318 | if(addressWSlide >= segCmd->vmaddr && 319 | addressWSlide < segCmd->vmaddr + segCmd->vmsize) { 320 | return iImg; 321 | } 322 | } 323 | cmdPtr += loadCmd->cmdsize; 324 | } 325 | } 326 | } 327 | return UINT_MAX; 328 | } 329 | 330 | uintptr_t bs_segmentBaseOfImageIndex(const uint32_t idx) { 331 | const struct mach_header* header = _dyld_get_image_header(idx); 332 | 333 | // Look for a segment command and return the file image address. 334 | uintptr_t cmdPtr = bs_firstCmdAfterHeader(header); 335 | if(cmdPtr == 0) { 336 | return 0; 337 | } 338 | for(uint32_t i = 0;i < header->ncmds; i++) { 339 | const struct load_command* loadCmd = (struct load_command*)cmdPtr; 340 | if(loadCmd->cmd == LC_SEGMENT) { 341 | const struct segment_command* segmentCmd = (struct segment_command*)cmdPtr; 342 | if(strcmp(segmentCmd->segname, SEG_LINKEDIT) == 0) { 343 | return segmentCmd->vmaddr - segmentCmd->fileoff; 344 | } 345 | } 346 | else if(loadCmd->cmd == LC_SEGMENT_64) { 347 | const struct segment_command_64* segmentCmd = (struct segment_command_64*)cmdPtr; 348 | if(strcmp(segmentCmd->segname, SEG_LINKEDIT) == 0) { 349 | return (uintptr_t)(segmentCmd->vmaddr - segmentCmd->fileoff); 350 | } 351 | } 352 | cmdPtr += loadCmd->cmdsize; 353 | } 354 | return 0; 355 | } 356 | 357 | @end 358 | -------------------------------------------------------------------------------- /Example/ANREye.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 26460D64FF89CA404F6F9D81 /* Pods_ANREye_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D477BAA2D2C568E57014022E /* Pods_ANREye_Tests.framework */; }; 11 | 4C41E60C351787236285654C /* Pods_ANREye_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17C8179D6BA79973C5639ED7 /* Pods_ANREye_Example.framework */; }; 12 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 13 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 14 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 15 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 16 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 17 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 18 | 9E24FA1C1E800235001AD0D7 /* ANREye.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E24FA1A1E800235001AD0D7 /* ANREye.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | 9E24FA2C1E800248001AD0D7 /* ANREye.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E24FA251E800248001AD0D7 /* ANREye.swift */; }; 20 | 9E24FA2D1E800248001AD0D7 /* AppBacktrace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E24FA271E800248001AD0D7 /* AppBacktrace.swift */; }; 21 | 9E24FA2E1E800248001AD0D7 /* BSBacktraceLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E24FA281E800248001AD0D7 /* BSBacktraceLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 22 | 9E24FA2F1E800248001AD0D7 /* BSBacktraceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E24FA291E800248001AD0D7 /* BSBacktraceLogger.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 31 | remoteInfo = ANREye; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 17C8179D6BA79973C5639ED7 /* Pods_ANREye_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ANREye_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 35ED069C36A11AD2F07466B2 /* Pods-ANREye_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ANREye_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ANREye_Tests/Pods-ANREye_Tests.debug.xcconfig"; sourceTree = ""; }; 38 | 4DA125C2EC1048CAF2DA4F0C /* Pods-ANREye_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ANREye_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ANREye_Tests/Pods-ANREye_Tests.release.xcconfig"; sourceTree = ""; }; 39 | 59386A9F151384074DAC6FE1 /* Pods-ANREye_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ANREye_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ANREye_Example/Pods-ANREye_Example.debug.xcconfig"; sourceTree = ""; }; 40 | 607FACD01AFB9204008FA782 /* ANREye_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ANREye_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 43 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 44 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 46 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 47 | 607FACE51AFB9204008FA782 /* ANREye_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ANREye_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 50 | 7189F980354AB0955EDDDD72 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 51 | 9E24FA181E800235001AD0D7 /* ANREye.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ANREye.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 9E24FA1A1E800235001AD0D7 /* ANREye.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ANREye.h; sourceTree = ""; }; 53 | 9E24FA1B1E800235001AD0D7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | 9E24FA251E800248001AD0D7 /* ANREye.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ANREye.swift; sourceTree = ""; }; 55 | 9E24FA271E800248001AD0D7 /* AppBacktrace.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppBacktrace.swift; sourceTree = ""; }; 56 | 9E24FA281E800248001AD0D7 /* BSBacktraceLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSBacktraceLogger.h; sourceTree = ""; }; 57 | 9E24FA291E800248001AD0D7 /* BSBacktraceLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSBacktraceLogger.m; sourceTree = ""; }; 58 | A97E529EF46C0E73BCF0936E /* Pods-ANREye_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ANREye_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-ANREye_Example/Pods-ANREye_Example.release.xcconfig"; sourceTree = ""; }; 59 | AEFB82F5E8C0849859110DCC /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 60 | D477BAA2D2C568E57014022E /* Pods_ANREye_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ANREye_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | F96FDA0B77D1A8DA5B6C3421 /* ANREye.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = ANREye.podspec; path = ../ANREye.podspec; sourceTree = ""; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | 4C41E60C351787236285654C /* Pods_ANREye_Example.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 26460D64FF89CA404F6F9D81 /* Pods_ANREye_Tests.framework in Frameworks */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | 9E24FA141E800235001AD0D7 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | 607FACC71AFB9204008FA782 = { 92 | isa = PBXGroup; 93 | children = ( 94 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 95 | 607FACD21AFB9204008FA782 /* Example for ANREye */, 96 | 607FACE81AFB9204008FA782 /* Tests */, 97 | 9E24FA191E800235001AD0D7 /* ANREye */, 98 | 607FACD11AFB9204008FA782 /* Products */, 99 | F481CFB638555D2CB490175F /* Pods */, 100 | BAD394CD69BF5C6D7739C24B /* Frameworks */, 101 | ); 102 | sourceTree = ""; 103 | }; 104 | 607FACD11AFB9204008FA782 /* Products */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 607FACD01AFB9204008FA782 /* ANREye_Example.app */, 108 | 607FACE51AFB9204008FA782 /* ANREye_Tests.xctest */, 109 | 9E24FA181E800235001AD0D7 /* ANREye.framework */, 110 | ); 111 | name = Products; 112 | sourceTree = ""; 113 | }; 114 | 607FACD21AFB9204008FA782 /* Example for ANREye */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 118 | 607FACD71AFB9204008FA782 /* ViewController.swift */, 119 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 120 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 121 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 122 | 607FACD31AFB9204008FA782 /* Supporting Files */, 123 | ); 124 | name = "Example for ANREye"; 125 | path = ANREye; 126 | sourceTree = ""; 127 | }; 128 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 607FACD41AFB9204008FA782 /* Info.plist */, 132 | ); 133 | name = "Supporting Files"; 134 | sourceTree = ""; 135 | }; 136 | 607FACE81AFB9204008FA782 /* Tests */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 607FACEB1AFB9204008FA782 /* Tests.swift */, 140 | 607FACE91AFB9204008FA782 /* Supporting Files */, 141 | ); 142 | path = Tests; 143 | sourceTree = ""; 144 | }; 145 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 607FACEA1AFB9204008FA782 /* Info.plist */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | F96FDA0B77D1A8DA5B6C3421 /* ANREye.podspec */, 157 | 7189F980354AB0955EDDDD72 /* README.md */, 158 | AEFB82F5E8C0849859110DCC /* LICENSE */, 159 | ); 160 | name = "Podspec Metadata"; 161 | sourceTree = ""; 162 | }; 163 | 9E24FA191E800235001AD0D7 /* ANREye */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 9E24FA201E800248001AD0D7 /* ANREye */, 167 | 9E24FA1A1E800235001AD0D7 /* ANREye.h */, 168 | 9E24FA1B1E800235001AD0D7 /* Info.plist */, 169 | ); 170 | path = ANREye; 171 | sourceTree = ""; 172 | }; 173 | 9E24FA201E800248001AD0D7 /* ANREye */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 9E24FA231E800248001AD0D7 /* Classes */, 177 | ); 178 | name = ANREye; 179 | path = ../../ANREye; 180 | sourceTree = ""; 181 | }; 182 | 9E24FA231E800248001AD0D7 /* Classes */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | 9E24FA251E800248001AD0D7 /* ANREye.swift */, 186 | 9E24FA261E800248001AD0D7 /* Backtrace */, 187 | ); 188 | path = Classes; 189 | sourceTree = ""; 190 | }; 191 | 9E24FA261E800248001AD0D7 /* Backtrace */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 9E24FA271E800248001AD0D7 /* AppBacktrace.swift */, 195 | 9E24FA281E800248001AD0D7 /* BSBacktraceLogger.h */, 196 | 9E24FA291E800248001AD0D7 /* BSBacktraceLogger.m */, 197 | ); 198 | path = Backtrace; 199 | sourceTree = ""; 200 | }; 201 | BAD394CD69BF5C6D7739C24B /* Frameworks */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 17C8179D6BA79973C5639ED7 /* Pods_ANREye_Example.framework */, 205 | D477BAA2D2C568E57014022E /* Pods_ANREye_Tests.framework */, 206 | ); 207 | name = Frameworks; 208 | sourceTree = ""; 209 | }; 210 | F481CFB638555D2CB490175F /* Pods */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 59386A9F151384074DAC6FE1 /* Pods-ANREye_Example.debug.xcconfig */, 214 | A97E529EF46C0E73BCF0936E /* Pods-ANREye_Example.release.xcconfig */, 215 | 35ED069C36A11AD2F07466B2 /* Pods-ANREye_Tests.debug.xcconfig */, 216 | 4DA125C2EC1048CAF2DA4F0C /* Pods-ANREye_Tests.release.xcconfig */, 217 | ); 218 | name = Pods; 219 | sourceTree = ""; 220 | }; 221 | /* End PBXGroup section */ 222 | 223 | /* Begin PBXHeadersBuildPhase section */ 224 | 9E24FA151E800235001AD0D7 /* Headers */ = { 225 | isa = PBXHeadersBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 9E24FA2E1E800248001AD0D7 /* BSBacktraceLogger.h in Headers */, 229 | 9E24FA1C1E800235001AD0D7 /* ANREye.h in Headers */, 230 | ); 231 | runOnlyForDeploymentPostprocessing = 0; 232 | }; 233 | /* End PBXHeadersBuildPhase section */ 234 | 235 | /* Begin PBXNativeTarget section */ 236 | 607FACCF1AFB9204008FA782 /* ANREye_Example */ = { 237 | isa = PBXNativeTarget; 238 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "ANREye_Example" */; 239 | buildPhases = ( 240 | F16460948FCD9B5B25284597 /* [CP] Check Pods Manifest.lock */, 241 | 607FACCC1AFB9204008FA782 /* Sources */, 242 | 607FACCD1AFB9204008FA782 /* Frameworks */, 243 | 607FACCE1AFB9204008FA782 /* Resources */, 244 | A96451F5DA7D704B7664BC42 /* [CP] Embed Pods Frameworks */, 245 | ); 246 | buildRules = ( 247 | ); 248 | dependencies = ( 249 | ); 250 | name = ANREye_Example; 251 | productName = ANREye; 252 | productReference = 607FACD01AFB9204008FA782 /* ANREye_Example.app */; 253 | productType = "com.apple.product-type.application"; 254 | }; 255 | 607FACE41AFB9204008FA782 /* ANREye_Tests */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "ANREye_Tests" */; 258 | buildPhases = ( 259 | 615430759EFF5FDC646B15B0 /* [CP] Check Pods Manifest.lock */, 260 | 607FACE11AFB9204008FA782 /* Sources */, 261 | 607FACE21AFB9204008FA782 /* Frameworks */, 262 | 607FACE31AFB9204008FA782 /* Resources */, 263 | ); 264 | buildRules = ( 265 | ); 266 | dependencies = ( 267 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 268 | ); 269 | name = ANREye_Tests; 270 | productName = Tests; 271 | productReference = 607FACE51AFB9204008FA782 /* ANREye_Tests.xctest */; 272 | productType = "com.apple.product-type.bundle.unit-test"; 273 | }; 274 | 9E24FA171E800235001AD0D7 /* ANREye */ = { 275 | isa = PBXNativeTarget; 276 | buildConfigurationList = 9E24FA1F1E800235001AD0D7 /* Build configuration list for PBXNativeTarget "ANREye" */; 277 | buildPhases = ( 278 | 9E24FA131E800235001AD0D7 /* Sources */, 279 | 9E24FA141E800235001AD0D7 /* Frameworks */, 280 | 9E24FA151E800235001AD0D7 /* Headers */, 281 | 9E24FA161E800235001AD0D7 /* Resources */, 282 | ); 283 | buildRules = ( 284 | ); 285 | dependencies = ( 286 | ); 287 | name = ANREye; 288 | productName = ANREye; 289 | productReference = 9E24FA181E800235001AD0D7 /* ANREye.framework */; 290 | productType = "com.apple.product-type.framework"; 291 | }; 292 | /* End PBXNativeTarget section */ 293 | 294 | /* Begin PBXProject section */ 295 | 607FACC81AFB9204008FA782 /* Project object */ = { 296 | isa = PBXProject; 297 | attributes = { 298 | LastSwiftUpdateCheck = 0720; 299 | LastUpgradeCheck = 0720; 300 | ORGANIZATIONNAME = CocoaPods; 301 | TargetAttributes = { 302 | 607FACCF1AFB9204008FA782 = { 303 | CreatedOnToolsVersion = 6.3.1; 304 | LastSwiftMigration = 0810; 305 | }; 306 | 607FACE41AFB9204008FA782 = { 307 | CreatedOnToolsVersion = 6.3.1; 308 | LastSwiftMigration = 0810; 309 | TestTargetID = 607FACCF1AFB9204008FA782; 310 | }; 311 | 9E24FA171E800235001AD0D7 = { 312 | CreatedOnToolsVersion = 8.2.1; 313 | DevelopmentTeam = L35WZWVC98; 314 | LastSwiftMigration = 0920; 315 | ProvisioningStyle = Automatic; 316 | }; 317 | }; 318 | }; 319 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "ANREye" */; 320 | compatibilityVersion = "Xcode 3.2"; 321 | developmentRegion = English; 322 | hasScannedForEncodings = 0; 323 | knownRegions = ( 324 | en, 325 | Base, 326 | ); 327 | mainGroup = 607FACC71AFB9204008FA782; 328 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 329 | projectDirPath = ""; 330 | projectRoot = ""; 331 | targets = ( 332 | 607FACCF1AFB9204008FA782 /* ANREye_Example */, 333 | 607FACE41AFB9204008FA782 /* ANREye_Tests */, 334 | 9E24FA171E800235001AD0D7 /* ANREye */, 335 | ); 336 | }; 337 | /* End PBXProject section */ 338 | 339 | /* Begin PBXResourcesBuildPhase section */ 340 | 607FACCE1AFB9204008FA782 /* Resources */ = { 341 | isa = PBXResourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 345 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 346 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | }; 350 | 607FACE31AFB9204008FA782 /* Resources */ = { 351 | isa = PBXResourcesBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | 9E24FA161E800235001AD0D7 /* Resources */ = { 358 | isa = PBXResourcesBuildPhase; 359 | buildActionMask = 2147483647; 360 | files = ( 361 | ); 362 | runOnlyForDeploymentPostprocessing = 0; 363 | }; 364 | /* End PBXResourcesBuildPhase section */ 365 | 366 | /* Begin PBXShellScriptBuildPhase section */ 367 | 615430759EFF5FDC646B15B0 /* [CP] Check Pods Manifest.lock */ = { 368 | isa = PBXShellScriptBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | ); 372 | inputPaths = ( 373 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 374 | "${PODS_ROOT}/Manifest.lock", 375 | ); 376 | name = "[CP] Check Pods Manifest.lock"; 377 | outputPaths = ( 378 | "$(DERIVED_FILE_DIR)/Pods-ANREye_Tests-checkManifestLockResult.txt", 379 | ); 380 | runOnlyForDeploymentPostprocessing = 0; 381 | shellPath = /bin/sh; 382 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 383 | showEnvVarsInLog = 0; 384 | }; 385 | A96451F5DA7D704B7664BC42 /* [CP] Embed Pods Frameworks */ = { 386 | isa = PBXShellScriptBuildPhase; 387 | buildActionMask = 2147483647; 388 | files = ( 389 | ); 390 | inputPaths = ( 391 | "${SRCROOT}/Pods/Target Support Files/Pods-ANREye_Example/Pods-ANREye_Example-frameworks.sh", 392 | "${BUILT_PRODUCTS_DIR}/ANREye/ANREye.framework", 393 | ); 394 | name = "[CP] Embed Pods Frameworks"; 395 | outputPaths = ( 396 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ANREye.framework", 397 | ); 398 | runOnlyForDeploymentPostprocessing = 0; 399 | shellPath = /bin/sh; 400 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ANREye_Example/Pods-ANREye_Example-frameworks.sh\"\n"; 401 | showEnvVarsInLog = 0; 402 | }; 403 | F16460948FCD9B5B25284597 /* [CP] Check Pods Manifest.lock */ = { 404 | isa = PBXShellScriptBuildPhase; 405 | buildActionMask = 2147483647; 406 | files = ( 407 | ); 408 | inputPaths = ( 409 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 410 | "${PODS_ROOT}/Manifest.lock", 411 | ); 412 | name = "[CP] Check Pods Manifest.lock"; 413 | outputPaths = ( 414 | "$(DERIVED_FILE_DIR)/Pods-ANREye_Example-checkManifestLockResult.txt", 415 | ); 416 | runOnlyForDeploymentPostprocessing = 0; 417 | shellPath = /bin/sh; 418 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 419 | showEnvVarsInLog = 0; 420 | }; 421 | /* End PBXShellScriptBuildPhase section */ 422 | 423 | /* Begin PBXSourcesBuildPhase section */ 424 | 607FACCC1AFB9204008FA782 /* Sources */ = { 425 | isa = PBXSourcesBuildPhase; 426 | buildActionMask = 2147483647; 427 | files = ( 428 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 429 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 430 | ); 431 | runOnlyForDeploymentPostprocessing = 0; 432 | }; 433 | 607FACE11AFB9204008FA782 /* Sources */ = { 434 | isa = PBXSourcesBuildPhase; 435 | buildActionMask = 2147483647; 436 | files = ( 437 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 438 | ); 439 | runOnlyForDeploymentPostprocessing = 0; 440 | }; 441 | 9E24FA131E800235001AD0D7 /* Sources */ = { 442 | isa = PBXSourcesBuildPhase; 443 | buildActionMask = 2147483647; 444 | files = ( 445 | 9E24FA2F1E800248001AD0D7 /* BSBacktraceLogger.m in Sources */, 446 | 9E24FA2D1E800248001AD0D7 /* AppBacktrace.swift in Sources */, 447 | 9E24FA2C1E800248001AD0D7 /* ANREye.swift in Sources */, 448 | ); 449 | runOnlyForDeploymentPostprocessing = 0; 450 | }; 451 | /* End PBXSourcesBuildPhase section */ 452 | 453 | /* Begin PBXTargetDependency section */ 454 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 455 | isa = PBXTargetDependency; 456 | target = 607FACCF1AFB9204008FA782 /* ANREye_Example */; 457 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 458 | }; 459 | /* End PBXTargetDependency section */ 460 | 461 | /* Begin PBXVariantGroup section */ 462 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 463 | isa = PBXVariantGroup; 464 | children = ( 465 | 607FACDA1AFB9204008FA782 /* Base */, 466 | ); 467 | name = Main.storyboard; 468 | sourceTree = ""; 469 | }; 470 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 471 | isa = PBXVariantGroup; 472 | children = ( 473 | 607FACDF1AFB9204008FA782 /* Base */, 474 | ); 475 | name = LaunchScreen.xib; 476 | sourceTree = ""; 477 | }; 478 | /* End PBXVariantGroup section */ 479 | 480 | /* Begin XCBuildConfiguration section */ 481 | 607FACED1AFB9204008FA782 /* Debug */ = { 482 | isa = XCBuildConfiguration; 483 | buildSettings = { 484 | ALWAYS_SEARCH_USER_PATHS = NO; 485 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 486 | CLANG_CXX_LIBRARY = "libc++"; 487 | CLANG_ENABLE_MODULES = YES; 488 | CLANG_ENABLE_OBJC_ARC = YES; 489 | CLANG_WARN_BOOL_CONVERSION = YES; 490 | CLANG_WARN_CONSTANT_CONVERSION = YES; 491 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 492 | CLANG_WARN_EMPTY_BODY = YES; 493 | CLANG_WARN_ENUM_CONVERSION = YES; 494 | CLANG_WARN_INT_CONVERSION = YES; 495 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 496 | CLANG_WARN_UNREACHABLE_CODE = YES; 497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 498 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 499 | COPY_PHASE_STRIP = NO; 500 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 501 | ENABLE_STRICT_OBJC_MSGSEND = YES; 502 | ENABLE_TESTABILITY = YES; 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_DYNAMIC_NO_PIC = NO; 505 | GCC_NO_COMMON_BLOCKS = YES; 506 | GCC_OPTIMIZATION_LEVEL = 0; 507 | GCC_PREPROCESSOR_DEFINITIONS = ( 508 | "DEBUG=1", 509 | "$(inherited)", 510 | ); 511 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 512 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 513 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 514 | GCC_WARN_UNDECLARED_SELECTOR = YES; 515 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 516 | GCC_WARN_UNUSED_FUNCTION = YES; 517 | GCC_WARN_UNUSED_VARIABLE = YES; 518 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 519 | MTL_ENABLE_DEBUG_INFO = YES; 520 | ONLY_ACTIVE_ARCH = YES; 521 | SDKROOT = iphoneos; 522 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 523 | }; 524 | name = Debug; 525 | }; 526 | 607FACEE1AFB9204008FA782 /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | ALWAYS_SEARCH_USER_PATHS = NO; 530 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 531 | CLANG_CXX_LIBRARY = "libc++"; 532 | CLANG_ENABLE_MODULES = YES; 533 | CLANG_ENABLE_OBJC_ARC = YES; 534 | CLANG_WARN_BOOL_CONVERSION = YES; 535 | CLANG_WARN_CONSTANT_CONVERSION = YES; 536 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 537 | CLANG_WARN_EMPTY_BODY = YES; 538 | CLANG_WARN_ENUM_CONVERSION = YES; 539 | CLANG_WARN_INT_CONVERSION = YES; 540 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 541 | CLANG_WARN_UNREACHABLE_CODE = YES; 542 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 543 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 544 | COPY_PHASE_STRIP = NO; 545 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 546 | ENABLE_NS_ASSERTIONS = NO; 547 | ENABLE_STRICT_OBJC_MSGSEND = YES; 548 | GCC_C_LANGUAGE_STANDARD = gnu99; 549 | GCC_NO_COMMON_BLOCKS = YES; 550 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 551 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 552 | GCC_WARN_UNDECLARED_SELECTOR = YES; 553 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 554 | GCC_WARN_UNUSED_FUNCTION = YES; 555 | GCC_WARN_UNUSED_VARIABLE = YES; 556 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 557 | MTL_ENABLE_DEBUG_INFO = NO; 558 | SDKROOT = iphoneos; 559 | VALIDATE_PRODUCT = YES; 560 | }; 561 | name = Release; 562 | }; 563 | 607FACF01AFB9204008FA782 /* Debug */ = { 564 | isa = XCBuildConfiguration; 565 | baseConfigurationReference = 59386A9F151384074DAC6FE1 /* Pods-ANREye_Example.debug.xcconfig */; 566 | buildSettings = { 567 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 568 | INFOPLIST_FILE = ANREye/Info.plist; 569 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 570 | MODULE_NAME = ExampleApp; 571 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | SWIFT_VERSION = 4.0; 574 | }; 575 | name = Debug; 576 | }; 577 | 607FACF11AFB9204008FA782 /* Release */ = { 578 | isa = XCBuildConfiguration; 579 | baseConfigurationReference = A97E529EF46C0E73BCF0936E /* Pods-ANREye_Example.release.xcconfig */; 580 | buildSettings = { 581 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 582 | INFOPLIST_FILE = ANREye/Info.plist; 583 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 584 | MODULE_NAME = ExampleApp; 585 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 586 | PRODUCT_NAME = "$(TARGET_NAME)"; 587 | SWIFT_VERSION = 4.0; 588 | }; 589 | name = Release; 590 | }; 591 | 607FACF31AFB9204008FA782 /* Debug */ = { 592 | isa = XCBuildConfiguration; 593 | baseConfigurationReference = 35ED069C36A11AD2F07466B2 /* Pods-ANREye_Tests.debug.xcconfig */; 594 | buildSettings = { 595 | FRAMEWORK_SEARCH_PATHS = ( 596 | "$(SDKROOT)/Developer/Library/Frameworks", 597 | "$(inherited)", 598 | ); 599 | GCC_PREPROCESSOR_DEFINITIONS = ( 600 | "DEBUG=1", 601 | "$(inherited)", 602 | ); 603 | INFOPLIST_FILE = Tests/Info.plist; 604 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 605 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 606 | PRODUCT_NAME = "$(TARGET_NAME)"; 607 | SWIFT_VERSION = 4.0; 608 | }; 609 | name = Debug; 610 | }; 611 | 607FACF41AFB9204008FA782 /* Release */ = { 612 | isa = XCBuildConfiguration; 613 | baseConfigurationReference = 4DA125C2EC1048CAF2DA4F0C /* Pods-ANREye_Tests.release.xcconfig */; 614 | buildSettings = { 615 | FRAMEWORK_SEARCH_PATHS = ( 616 | "$(SDKROOT)/Developer/Library/Frameworks", 617 | "$(inherited)", 618 | ); 619 | INFOPLIST_FILE = Tests/Info.plist; 620 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 621 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 622 | PRODUCT_NAME = "$(TARGET_NAME)"; 623 | SWIFT_VERSION = 4.0; 624 | }; 625 | name = Release; 626 | }; 627 | 9E24FA1D1E800235001AD0D7 /* Debug */ = { 628 | isa = XCBuildConfiguration; 629 | buildSettings = { 630 | CLANG_ANALYZER_NONNULL = YES; 631 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 632 | CLANG_WARN_INFINITE_RECURSION = YES; 633 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 634 | CODE_SIGN_IDENTITY = ""; 635 | CURRENT_PROJECT_VERSION = 1; 636 | DEBUG_INFORMATION_FORMAT = dwarf; 637 | DEFINES_MODULE = YES; 638 | DEVELOPMENT_TEAM = L35WZWVC98; 639 | DYLIB_COMPATIBILITY_VERSION = 1; 640 | DYLIB_CURRENT_VERSION = 1; 641 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 642 | INFOPLIST_FILE = ANREye/Info.plist; 643 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 644 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 645 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 646 | PRODUCT_BUNDLE_IDENTIFIER = com.zixun.ANREye; 647 | PRODUCT_NAME = "$(TARGET_NAME)"; 648 | SKIP_INSTALL = YES; 649 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 650 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 651 | SWIFT_VERSION = 4.0; 652 | TARGETED_DEVICE_FAMILY = "1,2"; 653 | VERSIONING_SYSTEM = "apple-generic"; 654 | VERSION_INFO_PREFIX = ""; 655 | }; 656 | name = Debug; 657 | }; 658 | 9E24FA1E1E800235001AD0D7 /* Release */ = { 659 | isa = XCBuildConfiguration; 660 | buildSettings = { 661 | CLANG_ANALYZER_NONNULL = YES; 662 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 663 | CLANG_WARN_INFINITE_RECURSION = YES; 664 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 665 | CODE_SIGN_IDENTITY = ""; 666 | CURRENT_PROJECT_VERSION = 1; 667 | DEFINES_MODULE = YES; 668 | DEVELOPMENT_TEAM = L35WZWVC98; 669 | DYLIB_COMPATIBILITY_VERSION = 1; 670 | DYLIB_CURRENT_VERSION = 1; 671 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 672 | INFOPLIST_FILE = ANREye/Info.plist; 673 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 674 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 675 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 676 | PRODUCT_BUNDLE_IDENTIFIER = com.zixun.ANREye; 677 | PRODUCT_NAME = "$(TARGET_NAME)"; 678 | SKIP_INSTALL = YES; 679 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 680 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 681 | SWIFT_VERSION = 4.0; 682 | TARGETED_DEVICE_FAMILY = "1,2"; 683 | VERSIONING_SYSTEM = "apple-generic"; 684 | VERSION_INFO_PREFIX = ""; 685 | }; 686 | name = Release; 687 | }; 688 | /* End XCBuildConfiguration section */ 689 | 690 | /* Begin XCConfigurationList section */ 691 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "ANREye" */ = { 692 | isa = XCConfigurationList; 693 | buildConfigurations = ( 694 | 607FACED1AFB9204008FA782 /* Debug */, 695 | 607FACEE1AFB9204008FA782 /* Release */, 696 | ); 697 | defaultConfigurationIsVisible = 0; 698 | defaultConfigurationName = Release; 699 | }; 700 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "ANREye_Example" */ = { 701 | isa = XCConfigurationList; 702 | buildConfigurations = ( 703 | 607FACF01AFB9204008FA782 /* Debug */, 704 | 607FACF11AFB9204008FA782 /* Release */, 705 | ); 706 | defaultConfigurationIsVisible = 0; 707 | defaultConfigurationName = Release; 708 | }; 709 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "ANREye_Tests" */ = { 710 | isa = XCConfigurationList; 711 | buildConfigurations = ( 712 | 607FACF31AFB9204008FA782 /* Debug */, 713 | 607FACF41AFB9204008FA782 /* Release */, 714 | ); 715 | defaultConfigurationIsVisible = 0; 716 | defaultConfigurationName = Release; 717 | }; 718 | 9E24FA1F1E800235001AD0D7 /* Build configuration list for PBXNativeTarget "ANREye" */ = { 719 | isa = XCConfigurationList; 720 | buildConfigurations = ( 721 | 9E24FA1D1E800235001AD0D7 /* Debug */, 722 | 9E24FA1E1E800235001AD0D7 /* Release */, 723 | ); 724 | defaultConfigurationIsVisible = 0; 725 | defaultConfigurationName = Release; 726 | }; 727 | /* End XCConfigurationList section */ 728 | }; 729 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 730 | } 731 | -------------------------------------------------------------------------------- /Example/ANREye.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/ANREye.xcodeproj/project.xcworkspace/xcshareddata/ANREye.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B" : 9223372036854775807, 8 | "BF1F56C483977AC36F575A9C50FB74A7EFF41C69" : 9223372036854775807 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "63AE1624-B395-4D6D-B69C-44BAD6C6D1FF", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B" : "ANREye\/", 13 | "BF1F56C483977AC36F575A9C50FB74A7EFF41C69" : "..\/.." 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "ANREye", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Example\/ANREye.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:zixun\/ANREye.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git.oschina.net:zixunapp\/AppSaber-MAC.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "BF1F56C483977AC36F575A9C50FB74A7EFF41C69" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Example/ANREye.xcodeproj/xcshareddata/xcschemes/ANREye-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/ANREye.xcodeproj/xcshareddata/xcschemes/ANREye.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Example/ANREye.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/ANREye.xcworkspace/xcshareddata/ANREye.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B" : 9223372036854775807, 8 | "BF1F56C483977AC36F575A9C50FB74A7EFF41C69" : 9223372036854775807 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "2845C86F-2D70-4C85-B508-12846456463C", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B" : "ANREye\/", 13 | "BF1F56C483977AC36F575A9C50FB74A7EFF41C69" : "..\/.." 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "ANREye", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Example\/ANREye.xcworkspace", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:zixun\/ANREye.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "0BF1E0159082E1DF1B0FEABA529982FE9AE6AF2B" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git.oschina.net:zixunapp\/AppSaber-MAC.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "BF1F56C483977AC36F575A9C50FB74A7EFF41C69" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Example/ANREye/ANREye.h: -------------------------------------------------------------------------------- 1 | // 2 | // ANREye.h 3 | // ANREye 4 | // 5 | // Created by zixun on 2017/3/20. 6 | // Copyright © 2017年 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ANREye. 12 | FOUNDATION_EXPORT double ANREyeVersionNumber; 13 | 14 | //! Project version string for ANREye. 15 | FOUNDATION_EXPORT const unsigned char ANREyeVersionString[]; 16 | 17 | #import "BSBacktraceLogger.h" 18 | 19 | // In this header, you should import all the public headers of your framework using statements like #import 20 | 21 | 22 | -------------------------------------------------------------------------------- /Example/ANREye/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ANREye 4 | // 5 | // Created by zixun on 12/23/2016. 6 | // Copyright (c) 2016 zixun. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/ANREye/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/ANREye/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/ANREye/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/ANREye/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/ANREye/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ANREye 4 | // 5 | // Created by zixun on 12/23/2016. 6 | // Copyright (c) 2016 zixun. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | import ANREye 12 | 13 | class ViewController: UIViewController { 14 | private var anrEye: ANREye! 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | self.anrEye = ANREye() 19 | self.anrEye.delegate = self 20 | self.anrEye.open(with: 1) 21 | var s = "" 22 | for _ in 0..<9999 { 23 | for _ in 0..<9999 { 24 | s.append("1") 25 | } 26 | } 27 | 28 | print("invoke") 29 | } 30 | 31 | } 32 | 33 | extension ViewController: ANREyeDelegate { 34 | 35 | func anrEye(anrEye:ANREye, 36 | catchWithThreshold threshold:Double, 37 | mainThreadBacktrace:String?, 38 | allThreadBacktrace:String?) { 39 | print("------------------") 40 | print(mainThreadBacktrace!) 41 | print("------------------") 42 | print(allThreadBacktrace!) 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'ANREye_Example' do 4 | pod 'ANREye', :path => '../' 5 | 6 | target 'ANREye_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ANREye (1.2.0) 3 | 4 | DEPENDENCIES: 5 | - ANREye (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | ANREye: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | ANREye: 4f3dc7dafb6fc0ed9f4d06fac7e08327232472e9 13 | 14 | PODFILE CHECKSUM: 43dc7e3969babdfdafcfc1af13cfdfff612d2d56 15 | 16 | COCOAPODS: 1.5.0 17 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import XCTest 3 | import ANREye 4 | 5 | class Tests: XCTestCase { 6 | 7 | override func setUp() { 8 | super.setUp() 9 | // Put setup code here. This method is called before the invocation of each test method in the class. 10 | } 11 | 12 | override func tearDown() { 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | super.tearDown() 15 | } 16 | 17 | func testExample() { 18 | // This is an example of a functional test case. 19 | XCTAssert(true, "Pass") 20 | } 21 | 22 | func testPerformanceExample() { 23 | // This is an example of a performance test case. 24 | self.measure() { 25 | // Put the code you want to measure the time of here. 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 陈奕龙(子循) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ANREye 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/Log4G.svg?style=flat)](http://cocoapods.org/pods/ANREye) 4 | [![License](https://img.shields.io/cocoapods/l/Log4G.svg?style=flat)](http://cocoapods.org/pods/ANREye) 5 | [![Platform](https://img.shields.io/cocoapods/p/Log4G.svg?style=flat)](http://cocoapods.org/pods/ANREye) 6 | 7 | [![Carthage compatible](https://img.shields.io/badge/Carthage-Compatible-brightgreen.svg?style=flat)](https://github.com/Carthage/Carthage) 8 | 9 | Class for monitor excessive blocking on the main thread 10 | 11 | ## Family 12 | This library is derived from the [GodEye](https://github.com/zixun/GodEye) project which can automaticly display Log,Crash,Network,ANR,Leak,CPU,RAM,FPS,NetFlow,Folder and etc with one line of code. Just like god opened his eyes 13 | 14 | ## Book & Principle 15 | 16 | **I has wrote a book named [《iOS监控编程》](https://www.qingdan.us/product/25),each chapter records the course function of the implementation details and the way to explore.sorry for english friends,this book wrote by chineses.** 17 | 18 | 19 | ## Installation 20 | 21 | ### CocoaPods 22 | ANREye is available through [CocoaPods](http://cocoapods.org). To install 23 | it, simply add the following line to your Podfile: 24 | 25 | ```ruby 26 | pod "ANREye" 27 | ``` 28 | 29 | ### Carthage 30 | Or, if you’re using [Carthage](https://github.com/Carthage/Carthage), add SwViewCapture to your Cartfile: 31 | 32 | ``` 33 | github "zixun/ANREye" 34 | ``` 35 | 36 | 37 | ## Usage 38 | ### open and add delegate 39 | 40 | ```swift 41 | self.anrEye = ANREye() 42 | self.anrEye.delegate = self 43 | self.anrEye.start(with: 1) 44 | ``` 45 | 46 | ### implement the delegate 47 | 48 | ```swift 49 | extension ViewController: ANREyeDelegate { 50 | 51 | func anrEye(anrEye:ANREye, 52 | catchWithThreshold threshold:Double, 53 | mainThreadBacktrace:String?, 54 | allThreadBacktrace:String?) { 55 | print("------------------") 56 | print(mainThreadBacktrace!) 57 | print("------------------") 58 | print(allThreadBacktrace!) 59 | } 60 | } 61 | ``` 62 | 63 | ### test code 64 | ```swift 65 | var s = "" 66 | for _ in 0..<9999 { 67 | for _ in 0..<9999 { 68 | s.append("1") 69 | } 70 | } 71 | 72 | print("invoke") 73 | ``` 74 | 75 | ## Author 76 | 77 | name: 陈奕龙 78 | 79 | twitter: [@zixun_](https://twitter.com/zixun_) 80 | 81 | email: chenyl.exe@gmail.com 82 | 83 | github: [zixun](https://github.com/zixun) 84 | 85 | blog: [子循(SubCycle)](http://zixun.github.io/) 86 | 87 | ## License 88 | 89 | ANREye is available under the MIT license. See the LICENSE file for more info. 90 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------