2017-02-15 40 views
1

我的應用程序發生崩潰時出現意外問題,我特別努力調試,因爲它發生在由iOS系統確定的時間的背景中。我對代碼有一些大寫的評論,這些代碼顯示了問題被追溯到哪裏。我希望這很清楚。可能的對象釋放錯誤,後臺應用程序崩潰block_invoke_5

我相信它與對象釋放有關。

  • 我已經嘗試使用__block在初始化對象之前,但 這沒有幫助。
  • 我也嘗試將錯誤的代碼行 錯誤地發送到主隊列,但這沒有幫助。

實際碰撞被列爲AppName的:__66- [BackgroundUpdateController initiateBackgroundHealthkitObservers] _block_invoke_5 + 160

我道歉,如果某些代碼不適合標準格式化和約定。我是從各種地方自學的,所以對代碼格式沒有適當的經驗。

非常感謝

#import "BackgroundUpdateController.h" 
NSUserDefaults *backgroundDefaults; 
@implementation BackgroundUpdateController 

-(id)init{ 
backgroundDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.HeartAnalyzer"]; 
return [super init]; 
} 

-(void)initiateBackgroundHealthkitObservers{ 
// Check we should be running here 
if(([backgroundDefaults integerForKey:@"sleepAnalysisEnabled"] != 1) || (![backgroundDefaults boolForKey:@"AutomaticSleepAdd"])) return; 
// Initiate some variables, Use __block to ensure the backgroundHealthStore object does not get deallocated 
__block HKHealthStore *backgroundHealthStore = [[HKHealthStore alloc] init]; 
HKQuantityType *activeEnergy = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned]; 
// Enable background delivery of active energy data from HealthKit 
[backgroundHealthStore enableBackgroundDeliveryForType:activeEnergy frequency:HKUpdateFrequencyHourly withCompletion:^(BOOL success, NSError *error) { 
}]; 
// Now setup an HKOberverQuery which triggers hourly if there are new active energy data points in HealthKit 
HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:activeEnergy predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError *error) { 
    UIApplicationState state = [[UIApplication sharedApplication] applicationState]; 
    if (state == UIApplicationStateBackground || state == UIApplicationStateInactive){// Only run when app is not in foreground 
     // Load some more variables with checks to ensure they are valid objects 
     NSDate *previousSavedDate = [backgroundDefaults objectForKey:@"DateBackgroundSleepLastSaved"]; 
     if(previousSavedDate == nil) previousSavedDate = [NSDate distantPast]; 
     NSDate *lastSleepCheck = [backgroundDefaults objectForKey:@"LastSleepCheck"]; 
     if(lastSleepCheck == nil) lastSleepCheck = [NSDate distantPast]; 
     // If the last save date was long enough ago and the last sleep check was long enough ago, proceed 
     if(([previousSavedDate timeIntervalSinceNow] < -(3600*18)) && ([lastSleepCheck timeIntervalSinceNow] < -(3600*2))){ 
      [backgroundDefaults setObject:[NSDate date] forKey:@"LastSleepCheck"]; 
      [backgroundDefaults setBool:NO forKey:@"BackgroundSleepFound"]; 
      SleepTimesCalculator *sleepClass = [[SleepTimesCalculator alloc] init]; 
      [sleepClass calculateSleepTimes:^{ 
       NSLog(@"Background sleep time calculations complete"); 
       if([backgroundDefaults boolForKey:@"BackgroundSleepFound"]){// Only continue is a sleep time was found 
        __block NSMutableArray *savedSleepObjects = [backgroundDefaults valueForKey:@"SleepTimesDataBase"]; 
        if(savedSleepObjects.count > 0){ 
          __block NSMutableDictionary *sleepObject = [savedSleepObjects objectAtIndex:0]; // THE __BLOCK USED TO PREVENT THE OBJECT BEING DEALLOCATED, STILL SEEMS TO BE BASED ON THE CRASH 
          NSDate *sleepStart = [NSDate dateWithTimeIntervalSinceReferenceDate:[[sleepObject valueForKey:@"CalculatedSleepTime"]integerValue]];// Get the sleep time start date object 
          NSDate *sleepEnd = [NSDate dateWithTimeIntervalSinceReferenceDate:[[sleepObject valueForKey:@"CalculatedWakeTime"]integerValue]]; 
          NSInteger sleepSavedToHealth = [[sleepObject valueForKey:@"SavedToHealth"] integerValue];// Check its not already been saved by some other element of the app 
          if(sleepSavedToHealth != 1){ 
           HKCategorySample *sleepSample = [HKCategorySample categorySampleWithType:[HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis] value:1 startDate:sleepStart endDate:sleepEnd];// Generate sleep object for HealthKit 
           [backgroundHealthStore saveObject:sleepSample withCompletion:^(BOOL success, NSError *error) { 
            if (!success) NSLog(@"Uncommon Error! saveObject:sleepSample"); 
            else{ 
             dispatch_async(dispatch_get_main_queue(), ^{// DISPATCH TO MAIN QUEUE AN ATTEMPTED FIX FOR CRASH 
              sleepObject = [savedSleepObjects objectAtIndex:0];// Choose the most recent sleep time to save 
              [sleepObject setValue:[NSNumber numberWithInteger:1] forKey:@"SavedToHealth"];// THIS IS WHERE THE 'Last Exception Backtrace (0)' ENDS UP 
              [savedSleepObjects replaceObjectAtIndex:0 withObject:sleepObject];// Replace the object which now has the 'Saved' tag 
              [backgroundDefaults setObject:[NSDate date] forKey:@"DateBackgroundSleepLastSaved"];// Save the data of the last time we reached this point 
              [backgroundDefaults setObject:savedSleepObjects forKey:@"SleepTimesDataBase"];// Save the sleep times back to the database 
             }); 
            } 
           }]; 
          } 
         completionHandler();// Call the completion handler as we've been throught the sleepObjects array 
        } 
        else completionHandler();// Call the completion handler anyway 
       } 
       else completionHandler();// Call the completion handler anyway 
      }]; 

     } 
     else completionHandler(); 
    } 
}]; 
[backgroundHealthStore executeQuery:query];// Execute the HealthKit healthstore query 
} 

@end 
+0

'__阻止用於防止OBJEC T正在死亡'你能解釋一下你的推理嗎?我認爲這是一個很大的誤解。 – ystack

回答

0

,前綴__block確實在sleepObject

擔保存在了@"CalculatedSleepTime"重點對象的我想你誤解了如何__block作品。 This將是一個很好的指導。

在代碼的簡要概述,好像[sleepObject valueForKey:@"CalculatedSleepTime"]正在恢復nil &沒有一個非空檢查你正在試圖提取integerValue

因此,可以考慮:

NSMutableDictionary *sleepObject = [savedSleepObjects objectAtIndex:0]; 
id calculatedSleepTime = [sleepObject valueForKey:@"CalculatedSleepTime"]; 

if(calculatedSleepTime){ 
    NSDate *sleepStart = [NSDate dateWithTimeIntervalSinceReferenceDate:[calculatedSleepTime integerValue]]; 
} 

它看起來像你也不需要__block前綴HKHealthStore *backgroundHealthStore = [[HKHealthStore alloc] init];

+0

非常感謝,我會做一些測試,並很快回來標記答案。歡呼 –

+0

@SimonEdwardes對此有何更新?你能解決嗎? – ystack

相關問題