2017-02-15 4 views
1

iOSシステムによって決定された時刻にバックグラウンドで発生するため、デバッグに特に苦労しているアプリでクラッシュする予期しない問題が発生しています。私は、問題がどこに追跡されているかを示すコードに大文字のコメントをいくつか持っています。私はこれがはっきりしていることを望む可能なオブジェクトの割り当て解除エラー、バックグラウンドのアプリケーションのクラッシュblock_invoke_5

私はそれがオブジェクトの割り当て解除と関係していると信じています。

  • 私はオブジェクトを初期化する前に__blockを使用しようとしましたが、 これは役に立ちませんでした。
  • 私はまた、コード の行をエラーでメインキューにディスパッチしようとしましたが、それは助けにはなりませんでした。実際のクラッシュはAppNameはと表示されている

:__66- [BackgroundUpdateController initiateBackgroundHealthkitObservers] _block_invoke_5 + 160

コードの一部は、標準の書式と規則に適合しない場合、私はお詫び申し上げます。私はさまざまな場所から独学で教えられているので、コードフォーマットについての適切な経験はありません。 __blockを前置

多くのおかげ

#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を防ぐために使用される__BLOCKあなたの推理を説明できますか?私はこれが大きな誤解だと思う。 – ystack

答えて

0

は、私はあなたがどのように__block作品を誤解していると思いますsleepObject

@"CalculatedSleepTime"キーのオブジェクトのない保証の有無を行います。 Thisはすばらしいガイドになります。

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

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

そしてそれ:[sleepObject valueForKey:@"CalculatedSleepTime"]はNULL値許容せずにnil &を返すようなコードの簡単な概要で

が、それはそうあなたがそう integerValue

を抽出しようとしている確認し、検討してくださいあなたも__blockプレフィックスを必要としないように見えるHKHealthStore *backgroundHealthStore = [[HKHealthStore alloc] init];

+0

これについて多くの感謝をします。私はいくつかのテストを行い、すぐに答えをマークするために戻ってきます。乾杯! –

+0

@SimonEdwardesこれに関する最新情報は?それを解決できましたか? – ystack

関連する問題