Note that there are some explanatory texts on larger screens.

plurals
  1. PORetain Cycle in DetailViewController - ARC Enabled
    primarykey
    data
    text
    <p>I am getting a retain cycle on presenting/dismissing my DetailViewController. Any help finding an opportunity for retain cycles in the code below would be greatly appreciated. </p> <p><strong>Question:</strong> Is there a retain cycle in the code posted below?</p> <p><img src="https://i.stack.imgur.com/4QizR.png" alt="enter image description here"></p> <p>iOS: 6</p> <p>xcode: 4.6</p> <p>tested: iphone 4 device</p> <p>ARC Enabled</p> <p><em>Edit:</em> added instruments photo. </p> <h2>DetailViewController.h</h2> <pre><code>@interface SRDetailViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *roomTitle; @property (weak, nonatomic) IBOutlet UIView *userScreenContainer; @property (weak, nonatomic) IBOutlet UIView *opponentScreenContainer; @property (weak, nonatomic) IBOutlet UILabel *statusLabel; @property (weak, nonatomic) IBOutlet UIButton *retryButton; @property (weak, nonatomic) IBOutlet UIProgressView *progressBar; @property (strong, nonatomic) NSTimer *progressTimer; @property (strong, nonatomic) NSTimer *retryTimer; @property (weak, nonatomic) IBOutlet UIView *bottomViewContainer; @property (strong, nonatomic) SRRoom *room; @property (strong, nonatomic) SROpenTokVideoHandler *openTokHandler; </code></pre> <h2>DetailViewController.m</h2> <pre><code>@interface SRDetailViewController () @property (strong, nonatomic) NSString* kApiKey; @property (strong, nonatomic) NSString* kSessionId; @property (strong, nonatomic) NSString* kToken; @end @implementation SRDetailViewController - (void)viewDidLoad { [super viewDidLoad]; [self configOpentTok]; [self performGetRoomRequest]; [self configNavBar]; [self configNotifcations]; [self configProgressBar]; } -(void)configSocialSharing { //check if it already exists for(UIView *subview in self.view.subviews){ if([subview isKindOfClass:[SRSocialSharing class]]){ return; } } //add off screen CGRect frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height, [[UIScreen mainScreen] bounds].size.width, 44); SRSocialSharing *share = [[SRSocialSharing alloc] initWithFrame:frame]; [self.view addSubview:share]; share.sharingURL = [self createUrlForSharing]; //animate in frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height-100, [[UIScreen mainScreen] bounds].size.width, 44); [UIView animateWithDuration:3 delay:2 options:UIViewAnimationOptionCurveEaseOut animations:^{ share.frame = frame; } completion:nil]; } -(NSURL *)createUrlForSharing { NSRange range = NSMakeRange(self.room.sessionId.length-7, 6); NSString *shortSessionId = [self.room.sessionId substringWithRange:range]; NSString *urlString = [NSString stringWithFormat:@"url/invites/%@/%@?sessionId=%@",self.room.topicId, [self opposingPosition:self.room.position],shortSessionId]; return [NSURL URLWithString:urlString]; } -(NSString *)opposingPosition:(NSString*)position { return ([position isEqualToString:@"agree"])? @"disagree" : @"agree"; } -(void) configOpentTok{ [self.openTokHandler registerUserVideoStreamContainer:self.userScreenContainer]; self.openTokHandler.userVideoStreamConatinerName = self.room.position; [self.openTokHandler registerOpponentOneVideoStreamContainer:self.opponentScreenContainer]; self.openTokHandler.opponentOneVideoStreamConatinerName = [self opposingPosition:self.room.position]; self.openTokHandler.shouldPublish = YES; self.openTokHandler.isObserving = NO; } -(void)configNavBar { UIImage *backButtonImage = [UIImage imageWithContentsOfFile:@"backButton"]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setFrame:CGRectMake(0, 0, 47, 32)]; [backButton setImage:backButtonImage forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(pressBackButton) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *navBackButton = [[UIBarButtonItem alloc] initWithCustomView:backButton]; [self.navigationItem setLeftBarButtonItem:navBackButton]; self.title = [self.room.position stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[self.room.position substringToIndex:1] capitalizedString]]; } -(void)pressBackButton{ self.navigationItem.leftBarButtonItem.enabled = NO; [self manageSafeClose]; double delayInSeconds = 3; //[self updateStatusLabel:@"Disconnecting" withColor:[UIColor grayColor]]; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [self.navigationController popViewControllerAnimated:YES]; }); } -(void)configNotifcations { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recieveNotifications:) name:kSROpenTokVideoHandlerNotifcations object:nil ]; } -(void)recieveNotifications:(NSNotification *)notification { if ([[notification name] isEqualToString:kSROpenTokVideoHandlerNotifcations]){ NSDictionary *userInfo = notification.userInfo; NSNumber *message = [userInfo objectForKey:@"message"]; [self statusMessage: message]; } } -(void)statusMessage:(NSNumber*)message{ NSString *result = nil; switch([message intValue]) { case 0: result = @"Disconnected"; break; case 1: result = @"Connecting..."; [self startRetryTimer]; break; case 2: result = @"Publishing Your Video..."; break; case 3: result = @"Searching for Idiots..."; break; case 4: result = @"Start!"; [self startProgressBar]; [self stopTimer:self.retryTimer]; break; case 5: [self stopTimer:self.progressTimer]; result = @"Stopped!"; break; case 6: [self stopTimer:self.progressTimer]; result = @"Disconnecting..."; break; case 7: result = @"Opponent failed to join. Retrying..."; [self performSelector:@selector(retry) withObject:nil afterDelay:4]; break; default: result = @"Retry"; } [self updateStatusLabel:result withColor:[self statusLabelColorPicker:message] animated:YES]; NSLog(@"STATUS LABEL UPDATE: %@", message); } -(UIColor*)statusLabelColorPicker:(NSString *)Message{ return [UIColor whiteColor]; } -(void)performGetRoomRequest{ __weak typeof(self) weakSelf = self; [[RKObjectManager sharedManager] getObject:weakSelf.room path:nil parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){ weakSelf.openTokHandler.kToken = weakSelf.room.token; weakSelf.openTokHandler.kSessionId = weakSelf.room.sessionId; weakSelf.roomTitle.text = weakSelf.room.title; weakSelf.navigationController.title = weakSelf.room.position; [weakSelf configSocialSharing]; [weakSelf.openTokHandler doConnectToRoomWithSession]; }failure:^(RKObjectRequestOperation *operation, NSError *error){ }]; } -(void)dealloc { self.room = nil; } -(void)manageSafeClose{ [self stopTimer:self.retryTimer]; [self stopTimer:self.progressTimer]; [self.openTokHandler safetlyCloseSession]; [[RKObjectManager sharedManager].operationQueue cancelAllOperations]; self.openTokHandler = nil; self.title = nil; self.navigationItem.leftBarButtonItem = nil; self.kApiKey = nil; self.kSessionId= nil; self.kToken= nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; [self doCloseRoom]; } -(void)doCloseRoom { __weak typeof(self) weakSelf = self; [[RKObjectManager sharedManager] deleteObject:weakSelf.room path:nil parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){ //NSLog(@"Mapping result %@", mappingResult); } failure:nil ]; } -(void)startRetryTimer { NSLog(@"Timer Started"); self.retryTimer = [NSTimer scheduledTimerWithTimeInterval:(60*5) target:self selector:@selector(retry) userInfo:nil repeats:YES]; } -(void)retry { [self doCloseRoom]; [self performSelector:@selector(performGetRoomRequest) withObject:nil afterDelay:4]; } #pragma mark - label - (void)updateStatusLabel:(NSString *) message withColor:(UIColor*) color animated:(bool) animated { self.statusLabel.text = message; if (animated) { [self fadeOutFadeInAnimation:self.statusLabel andColor:color]; } else{ [SRAnimationHelper stopAnimations:self.statusLabel]; } } - (void)fadeOutFadeInAnimation:(UILabel *)label andColor:(UIColor*)color { //add animation [label.layer addAnimation:[SRAnimationHelper fadeOfRoomStatusLabel] forKey:nil]; //change label color label.textColor = color; } #pragma mark - Progress Bar -(void)configProgressBar { self.progressBar.progressTintColor = [UIColor orangeColor]; } -(void)startProgressBar { self.progressBar.hidden = NO; self.progressBar.progress = 0; self.progressTimer = [NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(changeProgressValue) userInfo:nil repeats:YES]; } -(void)stopTimer: (NSTimer*)timer { [timer invalidate]; timer = nil; } - (void)changeProgressValue { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ float progressValue = self.progressBar.progress; progressValue += .00834; if (progressValue &gt; .99) { progressValue = 1; [self stopTimer:self.progressTimer]; return; } NSString* time =[NSString stringWithFormat:@"%.0f", 60 - ceil(progressValue*60)]; NSLog(@"Progress Value %f Time %@", progressValue, time); NSString *message = [NSString stringWithFormat:@"Time Left: %@", time]; dispatch_async(dispatch_get_main_queue(), ^(void) { self.progressBar.progress = progressValue; [self updateStatusLabel:message withColor:[UIColor whiteColor] animated:NO]; }); }); } @end </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload