2010-12-03 1 views
0

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 메서드에서 루프로 인해 메모리 누수가 상당히 많이 걸립니다. 발생하는 메모리 누출량을 줄이는 방법에 대해 올바른 방향으로 나를 인도 할 수 있는지 궁금합니다. 아마 그것은 최고의 코드가 아닙니다 ... 다른 영역에 대한 도움은 크게 감사 할 것입니다.for 루프에서 메모리 누수가 발생했습니다 (Objective-C iPhone)

// SearchViewController.h 

#import <UIKit/UIKit.h> 
#import "VenueDetailViewController.h" 
#import "OverlayViewController.h" 
#import "TBXML.h" 
#import "CoreLocationController.h" 

@interface SearchViewController : UIViewController <UITableViewDelegate, UISearchBarDelegate, CoreLocationControllerDelegate> { 
    VenueDetailViewController *venueDetailView; 
    IBOutlet UITableView *tv; 
    NSString *navBarTitle; 
    NSMutableArray *venues; 
    NSMutableArray *primaryCategories; 
    NSString *categoryId; 

    //Search properties. 
    OverlayViewController *overlayView; 
    IBOutlet UISearchBar *searchBar; 
    BOOL letUserSelectRow; 

    //Core location properties. 
    CoreLocationController *CLController; 

    BOOL searching; 

    NSMutableData *responseData; 
} 

@property (nonatomic, retain) NSString *navBarTitle; 
@property (nonatomic, retain) CoreLocationController *CLController; 
@property (nonatomic, retain) VenueDetailViewController *venueDetailView; 
@property (nonatomic, retain) OverlayViewController *overlayView; 
@property (nonatomic, retain) IBOutlet UITableView *tv; 
@property (nonatomic, retain) NSMutableArray *venues; 
@property (nonatomic, retain) NSMutableArray *primaryCategories; 
@property (nonatomic, retain) NSString *categoryId; 

- (void)doneSearching_Clicked:(id)sender; 
- (void)findLocations:(id)sender; 
- (void)loadPlacesWithLat:(NSString *)lat andLong:(NSString *)lng; 
- (void)findPostcode:(NSString *)postcode; 
- (void)showReloadButton; 

@end 

// SearchViewController.m 

#import "SearchViewController.h" 
#import "GenericCell.h" 
#import "FSVenue.h" 
#import "AsyncImageView.h" 
#import "Helper.h" 
#import "JSON.h" 

@implementation SearchViewController 

@synthesize tv; 
@synthesize venueDetailView, overlayView; 
@synthesize CLController; 
@synthesize navBarTitle; 
@synthesize venues, primaryCategories; 
@synthesize categoryId; 

- (void)viewDidLoad { 
    //Set the title. 
    navBarTitle = @"Nearby Places"; 
    self.title = navBarTitle; 

    //Set background and border to clear (to allow for background image to be visible). 
    tv.backgroundColor = [UIColor clearColor]; 
    [tv setSeparatorColor:[UIColor clearColor]]; 

    //Add the search bar. 
    tv.tableHeaderView = searchBar; 
    searchBar.autocorrectionType = UITextAutocorrectionTypeNo; 

    letUserSelectRow = YES; 

    venues = [[NSMutableArray alloc] init]; 
    primaryCategories = [[NSMutableArray alloc] init]; 

    //Core location init. 
    CLController = [[CoreLocationController alloc] init]; 
    CLController.delegate = self; 

    //Add a refresh icon to the top right navigation bar. 
    [self showReloadButton]; 

    if (self.categoryId != nil) { 
     [self findLocations:nil]; 
    } 

    searching = NO; 

    [super viewDidLoad]; 
} 

- (void)showReloadButton { 
    UIBarButtonItem *refreshItem = [[UIBarButtonItem alloc] 
            initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh 
            target:self 
            action:@selector(findLocations:)]; 

    self.navigationItem.rightBarButtonItem = refreshItem; 
    [refreshItem release]; 
} 

#pragma mark - 
#pragma mark Nearby Places/Core Location 

- (void)findLocations:(id)sender { 
    // Display loading overlay view. 
    if (!searching) { 
     [Helper beginLoading:self.view withTitle:navBarTitle]; 

     [self doneSearching_Clicked:nil]; 

     //Calls locationUpdate delegate method. 
     [CLController.locMgr startUpdatingLocation]; 

     searching = YES; 
    } 
} 

- (void)locationUpdate:(CLLocation *)location { 
    NSString *lat; 
    NSString *lng; 
#if !(TARGET_IPHONE_SIMULATOR) 
    lat = [NSString stringWithFormat:@"%f", location.coordinate.latitude]; 
    lng = [NSString stringWithFormat:@"%f", location.coordinate.longitude]; 
#else 
    lat = @"-37.816016"; 
    lng = @"144.969717"; 
#endif 

    [self loadPlacesWithLat:lat andLong:lng]; 
} 

- (void)locationError:(NSError *)error { 
    NSLog(@"locationError: %@", [error description]); 
} 

- (void)loadPlacesWithLat:(NSString *)lat andLong:(NSString *)lng { 
    [CLController.locMgr stopUpdatingLocation]; 

    responseData = [[NSMutableData data] retain]; 
    NSString *url = [NSString stringWithFormat:@"https://api.foursquare.com/v1/venues.json?geolat=%@&geolong=%@", lat, lng]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; 
    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
} 

- (void)findPostcode:(NSString *)pcode { 
    //Webservice URL: http://ws.geonames.org/findNearbyPostalCodes?postalcode=2000&country=AU&style=SHORT&maxRows=1 

    NSString *suburb; 
    NSString *postcode; 
    NSString *lat1; 
    NSString *lng1; 

    // load and parse an xml string. 
    TBXML* tbxml = [[TBXML alloc] initWithURL:[NSURL URLWithString: 
             [NSString stringWithFormat:@"http://ws.geonames.org/findNearbyPostalCodes?postalcode=%@&country=AU&style=SHORT&maxRows=1", 
             pcode]]]; 

    // obtain root element. 
    TBXMLElement *root = tbxml.rootXMLElement; 

    // if root element is valid. 
    if (root) { 
     // search for the first geonames element within the root elements children. 
     TBXMLElement *code = [TBXML childElementNamed:@"code" parentElement:root]; 

     if (code != nil) { 
      // find the lat child element of the code element. 
      TBXMLElement *lat = [TBXML childElementNamed:@"lat" parentElement:code]; 

      if (lat != nil) { 
       lat1 = [TBXML textForElement:lat]; 
      } 

      // find the long child element of the code element. 
      TBXMLElement *lng = [TBXML childElementNamed:@"lng" parentElement:code]; 

      if (lng != nil) { 
       lng1 = [TBXML textForElement:lng]; 
      } 

      // find the postalcode child element of the code element. 
      TBXMLElement *postalcode = [TBXML childElementNamed:@"postalcode" parentElement:code]; 

      if (postalcode != nil) { 
       postcode = [TBXML textForElement:postalcode]; 
      } 

      // find the postalcode child element of the code element. 
      TBXMLElement *name = [TBXML childElementNamed:@"name" parentElement:code]; 

      if (name != nil) { 
       suburb = [TBXML textForElement:name]; 
      } 

      NSLog(@"Searching Postcode %@ (%@) ...", postcode, suburb); 
      NSLog(@" Lat - %@", lat1); 
      NSLog(@" Long - %@", lng1); 

      [self loadPlacesWithLat:lat1 andLong:lng1]; 
     } 
    } 

    // release resources 
    [tbxml release]; 
} 

#pragma mark - 
#pragma mark JSON Over HTTP 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    [responseData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [responseData appendData:data]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog(@"connectin didFailWithError: %@", [error description]); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    [connection release]; 

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; 
    //[responseData release]; 

    NSDictionary *dictionary = [responseString JSONValue]; 
    [responseString release]; 

    NSArray *venueArray = [[[dictionary valueForKeyPath:@"groups"] objectAtIndex:0] valueForKeyPath:@"venues"]; 

    if ([dictionary valueForKeyPath:@"error"] != nil) { 
     [Helper displayAlertMessage:[dictionary valueForKeyPath:@"error"] withTitle:@"Foursquare"]; 
    } 

    for (id result in venueArray) { 
     FSVenue *venue = [[FSVenue alloc] init]; 
     venue.name = [result valueForKeyPath:@"name"]; 
     venue.venueId = [result valueForKeyPath:@"id"]; 
     venue.geoLat = [result valueForKeyPath:@"geolat"]; 
     venue.geoLong = [result valueForKeyPath:@"geolong"]; 

     NSDictionary *primaryCategoryDict = [result valueForKeyPath:@"primarycategory"]; 

     FSPrimaryCategory *primaryCategory = [[FSPrimaryCategory alloc] init]; 
     primaryCategory.iconUrl = [primaryCategoryDict valueForKeyPath:@"iconurl"]; 
     primaryCategory.iconUrl = [primaryCategory.iconUrl stringByReplacingOccurrencesOfString:@".png" withString:@"_64.png"]; 
     primaryCategory.nodeName = [primaryCategoryDict valueForKeyPath:@"nodename"]; 
     primaryCategory.primaryCategoryId = [NSString stringWithFormat:@"%@", [primaryCategoryDict valueForKeyPath:@"id"]]; 

     //Check if categories match the category selected from the FSCategory controllers. 
     if (self.categoryId != nil) { 
      if ([self.categoryId isEqualToString:primaryCategory.primaryCategoryId]) { 
       [venues addObject:venue]; 
       [venue release]; 
       [primaryCategories addObject:primaryCategory]; 
       [primaryCategory release]; 
      } else { 
       [venue release]; 
       [primaryCategory release]; 
      } 
     } else { 
      [venues addObject:venue]; 
      [venue release]; 
      [primaryCategories addObject:primaryCategory]; 
      [primaryCategory release]; 
     } 
    } 

    [tv reloadData]; 

    //Hide loading overlay view. 
    [Helper finishLoading:navBarTitle]; 

    searching = NO; 
} 

#pragma mark - 
#pragma mark Table View 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return [venues count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"GenericCell"; 

    GenericCell *cell = (GenericCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    if (cell == nil) { 
     NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:nil options:nil]; 

     for (id currentObject in topLevelObjects) { 
      if ([currentObject isKindOfClass:[UITableViewCell class]]) { 
       cell = (GenericCell *)currentObject; 
       break; 
      } 
     } 
    } else { 
     AsyncImageView *oldImage = (AsyncImageView *) 
     [cell.contentView viewWithTag:999]; 
     [oldImage removeFromSuperview]; 
    } 

    FSPrimaryCategory *primaryCategory = (FSPrimaryCategory *)[primaryCategories objectAtIndex:indexPath.row]; 
    FSVenue *venue = (FSVenue *)[venues objectAtIndex:indexPath.row]; 

    AsyncImageView *asyncImage = [[[AsyncImageView alloc] initWithFrame:CGRectMake(3, 3, 48, 48)] autorelease]; 
    asyncImage.tag = 999; 

    NSURL *url = [NSURL URLWithString:primaryCategory.iconUrl]; 
    [asyncImage loadImageFromURL:url]; 
    [cell.contentView addSubview:asyncImage]; 

    //The two images are 1x140 vertical gradients that UIKit automatically stretches horizontally to fit the width of the cell. 
    cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Cell_1x140.png"]]; 
    cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellSelected_1x140.png"]]; 

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    cell.titleLabel.text = venue.name; 

    return cell; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (venueDetailView == nil) { 

     venueDetailView = [[VenueDetailViewController alloc] initWithNibName:@"VenueDetailViewController" bundle:[NSBundle mainBundle]]; 

     FSVenue *venue = (FSVenue *)[venues objectAtIndex:indexPath.row]; 

     venueDetailView.vid = venue.venueId; 

     [self.navigationController pushViewController:venueDetailView animated:YES]; 
    } 

    venueDetailView = nil; 
    [venueDetailView release]; 
} 

- (NSIndexPath *)tableView :(UITableView *)theTableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (letUserSelectRow) 
     return indexPath; 
    else 
     return nil; 
} 

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (indexPath.row % 2) { 
     [cell setBackgroundColor:[UIColor colorWithRed:((float)173/255.0f) green:((float)173/255.0f) blue:((float)176/255.0f) alpha:.60]]; 
    } else { 
     [cell setBackgroundColor:[UIColor colorWithRed:((float)152/255.0f) green:((float)152/255.0f) blue:((float)156/255.0f) alpha:.60]]; 
    } 

    cell.selectionStyle = UITableViewCellSelectionStyleGray; 
} 

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    NSString *titleHeader; 

    if ([venues count] == 0) { 
     titleHeader = @"No venues were found."; 
    } else { 
     titleHeader = @""; 
    } 

    return titleHeader; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    return 55; 
} 

#pragma mark - 
#pragma mark Search Bar 

- (void)searchBarTextDidBeginEditing:(UISearchBar *)theSearchbar { 
    //Add the overlay view. 
    if (overlayView == nil) 
     overlayView = [[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:[NSBundle mainBundle]]; 

    CGFloat yaxis = self.navigationController.navigationBar.frame.size.height; 
    CGFloat width = self.view.frame.size.width; 
    CGFloat height = self.view.frame.size.height; 

    //Parameters x = origin on x-axis, y = origin on y-axis. 
    CGRect frame = CGRectMake(0, yaxis, width, height); 
    overlayView.view.frame = frame; 
    overlayView.view.backgroundColor = [UIColor grayColor]; 
    overlayView.view.alpha = 0.5; 

    overlayView.searchView = self; 

    [tv insertSubview:overlayView.view aboveSubview:self.parentViewController.view]; 

    letUserSelectRow = NO; 
    tv.scrollEnabled = NO; 
} 

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)theSearchBar { 
    searchBar.showsScopeBar = YES; 
    [searchBar sizeToFit]; 

    [searchBar setShowsCancelButton:YES animated:YES]; 

    return YES; 
} 

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)theSearchBar { 
    searchBar.showsScopeBar = NO; 
    [searchBar sizeToFit]; 

    [searchBar setShowsCancelButton:NO animated:YES]; 

    [self doneSearching_Clicked:nil]; 

    return YES; 
} 

- (void) doneSearching_Clicked:(id)sender { 
    [searchBar resignFirstResponder]; 

    letUserSelectRow = YES; 
    tv.scrollEnabled = YES; 

    [overlayView.view removeFromSuperview]; 
    [overlayView release]; 
    overlayView = nil; 

    //Reverse geocode postcode entered. 
    if (![searchBar.text isEqualToString:@""]) { 
     [self findPostcode:searchBar.text]; 
     searchBar.text = @""; 
     [tv reloadData]; 
    } 
} 

- (void)searchBarCancelButtonClicked:(UISearchBar *)theSearchBar { 
    [self doneSearching_Clicked:nil]; 
} 

- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar { 
    [searchBar resignFirstResponder]; 
} 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [tv reloadData]; 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

- (void)viewDidUnload { 
    [super viewDidUnload]; 
} 

- (void)dealloc { 
    [navBarTitle release]; 
    [venueDetailView release]; 
    [CLController release]; 
    [tv release]; 
    [venues release]; 
    [primaryCategories release]; 
    [categoryId release]; 
    [responseData release]; 
    [super dealloc]; 
} 

@end 
+0

안녕하세요

@interface MyObject : UIViewController <UITableViewDelegate,UITableViewDataSource> { NSMutableArray *venues; NSMutableArray *primaryCategories; } @property (nonatomic,retain) NSMutableArray *venues; @property (nonatomic,retain) NSMutableArray *primaryCategories; 

개체의 .H 파일에서

. self.categoryId가 primaryCategoryId와 같지 않을 경우를 대비하여 else 문을 먼저 추가 한 다음 venue/primaryCategory를 해제해야합니다. – Vivi

답변

5

누출이있을 수 있습니다. 난 그냥 분기의 [primaryCategory release] (그리고 venue 동일)을 인수로 루프의 끝에 넣어.

나중에 도움을 받으려면 XCode의 "빌드 및 분석"모드가 좋을 것입니다.이 모드에서는 이러한 종류의 코드 흐름 누출을 정적으로 감지하고 정확히 어디에 할당이 유출되었는지 알려줍니다.

+0

I <3 Cmd-Shift-A – Justin

+1

그래서 \ o/\ o/ – Vivi

+0

<3 Cmd-Shift-A도 가능합니다! 음. ;-) – fuzz

0

당신은 if 문 u는 다른이 if 문 .. 때문에 내부에서, 하나의 누출 primaryCategory이 때문에 메모리의 가능성이 유출되어 self.categoryId != nil![self.categoryId isEqualToString:primaryCategory.primaryCategoryId], 다음 primaryCategoryvenue 경우

+1

Justicepenny : 정교하게 주시겠습니까? if 문 안에 또 다른 if 문을 사용하는 것이 무엇이 잘못되었으며 어떻게 이로 인해 메모리 누수가 발생할 수 있습니까? primaryCategories 배열을 추가 한 후에 primaryCategory를 공개하겠습니까? – fuzz

+0

if ([self.categoryId isEqualToString : primaryCategory.primaryCategoryId]) { [장소 addObject : 장소]; [장소 공개]; [primaryCategories addObject : primaryCategory]; [primaryCategory release]; } – justicepenny

+0

if if, this if 문에 들어가지 않겠습니까 ??? – justicepenny

1

당신은 venueself.categoryId이 설정되어 있지만 primaryCategory.primaryCategoryId 일치하지 않을 때마다 primaryCategory 누출된다.

귀하의 코드는 확실히 정리 될 수있다 :

  • -[FSVenue initWithResult:] 방법을 추가합니다.
  • -[FSPrimaryCategory initWithDictionary:] 방법을 추가하십시오.
  • 장치를 기반으로 한 고해상도 아이콘의 사용 여부를 결정하십시오.
  • 루프 끝에있는 if 문에는 중복 된 코드가 들어 있습니다. 대신이 일을 생각해 보면 객체를 생성 할 때마다
 
for (...) { 
    ... 

    //Check if categories match the category selected from the FSCategory controllers. 
    if (self.categoryId 
     && ![self.categoryId isEqualToString:primaryCategory.primaryCategoryId]) { 
     [venue release]; 
     [primaryCategory release]; 
     continue; 
    } 

    [venues addObject:venue]; 
    [venue release]; 

    [primaryCategories addObject:primaryCategory]; 
    [primaryCategory release]; 
} 
  • autorelease을 사용하는 것이 좋습니다. 그럼 처음부터 아무것도 누출하지 않았을거야! 그들은 조건이되는 배열에 삽입 충족하지 않는
+0

자동 복구는 게으른 (잠재적으로 위험한) 솔루션입니다. 이 점을 고려하지 마십시오 : P 나는 다른 점들에 동의합니다. – Vivi

+0

또한 필자는 필자의 요구에 맞게 [FSVenue initWithResult :] 및 [FSPrimaryCategory initWithDictionary :] 메서드를 구현하는 것이 가장 좋은 방법인지 알고 싶습니다. if 문에 대한 솔루션을 제공해 주셔서 감사합니다. 매우 감사. – fuzz

+0

그래, 여전히 venue 및 primaryCategory 개체로 메모리 누수가 발생합니다. 잘못 됐어. – fuzz

1
venues = [[NSMutableArray alloc] init]; 
primaryCategories = [[NSMutableArray alloc] init]; 

for (id result in venueArray) { 
    FSVenue *venue = [[FSVenue alloc] init]; 
    venue.name = [result valueForKeyPath:@"name"]; 
    venue.venueId = [result valueForKeyPath:@"id"]; 
    venue.geoLat = [result valueForKeyPath:@"geolat"]; 
    venue.geoLong = [result valueForKeyPath:@"geolong"]; 

    NSDictionary *primaryCategoryDict = [result valueForKeyPath:@"primarycategory"]; 

    FSPrimaryCategory *primaryCategory = [[FSPrimaryCategory alloc] init]; 
    primaryCategory.iconUrl = [primaryCategoryDict valueForKeyPath:@"iconurl"]; 
    primaryCategory.iconUrl = [primaryCategory.iconUrl stringByReplacingOccurrencesOfString:@".png" withString:@"_64.png"]; 
    primaryCategory.nodeName = [primaryCategoryDict valueForKeyPath:@"nodename"]; 
    primaryCategory.primaryCategoryId = [NSString stringWithFormat:@"%@", [primaryCategoryDict valueForKeyPath:@"id"]]; 

    //Check if categories match the category selected from the FSCategory controllers. 
    if (self.categoryId != nil) { 
     if ([self.categoryId isEqualToString:primaryCategory.primaryCategoryId]) { 
      [venues addObject:venue]; 

      [primaryCategories addObject:primaryCategory]; 
     } 
    } else { 
     [venues addObject:venue]; 

     [primaryCategories addObject:primaryCategory]; 
    } 
    [primaryCategory release]; 
    [venue release]; 
} 

당신은 장소와 primaryCategory을 누출하고 있습니다. 이 루프의 올바른 구조는 위에 있습니다. 배열 '장소'와 'primaryCategories'는 ivars이고 클래스의 dealloc 메소드에서 해당 배열을 놓습니다. (그렇지 않으면 그 배열도 새어 나옵니다.)

+0

이것은 맞습니다. 나는 그것들을 ivars이기 때문에 클래스의 dealloc 메소드에서 그들을 풀어 놓을 것이다. – fuzz

+0

이후 나는 for 루프가 아닌 두 배열의 init을 viewDidLoad()로 옮겼습니다. – fuzz

+0

아참. for 루프를 사용하면 다음과 같이 표시됩니다. *** - [FSPrimaryCategory iconUrl] : 메시지가 할당 취소 된 인스턴스에 전송되었습니다. 0x98f39e0 – fuzz

1

Jeremy의 대답에 토론을 추가 한 다음 코드를 제안합니다. 개체의하는 .m 파일

@implementation MyObject 

@synthesize venues; 
@synthesize primaryCategories; 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.venues = [[NSMutableArray alloc] init]; 
    self.primaryCategories = [[NSMutableArray alloc] init]; 
} 

- (void)whatEverMethodYouLike { 
    // The for loop here (with proper deallocs) 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    FSPrimaryCategory *primaryCategory = (FSPrimaryCategory *)[primaryCategories objectAtIndex:indexPath.row]; 
    // Et caetera 
} 

- (void)dealloc { 
    [self.venues release]; 
    [self.primaryCategories release]; 
    [super dealloc]; 
} 
+0

코드를 보내 주셔서 감사합니다. 이것은 내가 이미하고있는 일입니다. 유일한 차이점은 내 venues 및 primaryCategories 배열이 viewDidLoad()에서 초기화되는 대신 루프 전에 초기화된다는 점입니다. 그래도 코드를 제공하는 데 시간을내어 주셔서 감사합니다. – fuzz

+0

하나의 질문이지만, 나는 결코 내 자기의 "자기"를 사용하지 않습니다. 이 나쁜 습관인가? – fuzz

+0

아니, 괜찮아, 내가 속성을 사용하여 내 vars을 정의 할 때마다 "자기"를 사용하는 데 사용되는 컨텍스트에 따라 달라집니다 : – Vivi

관련 문제