iphone - 何时在 Objective-C 中使用属性?

标签 iphone objective-c ios properties

我在这里有一个问题:Confusing double free error message/memory leak in iPhone app我认为需要一个新问题来回答。

我感兴趣的代码在那个问题中,但我会在这里重新发布

#import <UIKit/UIKit.h>
#import "MyManager.h"

@interface ListOfCarShares : UITableViewController <NSXMLParserDelegate>
{
    NSURLConnection *connection;
    NSMutableData *carsharexml;
    NSMutableArray *ldestination;
    NSMutableArray *ldeparts_from;
    NSMutableArray *lcs_id;
    NSMutableArray *ltime;
    NSMutableString *currentElement;

    NSMutableString *tdest;
    NSMutableString *tfrom;
    NSMutableString *ttime;
    NSMutableString *tid;
}

-(void)fetchcarshares;
@property (nonatomic, assign) IBOutlet UITableViewCell *maincell;

@end

#import "ListOfCarShares.h"

@implementation ListOfCarShares
@synthesize maincell;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qualifiedName
    attributes:(NSDictionary *)attributeDict
{
    currentElement = [[elementName copy] autorelease];
    if ([elementName isEqualToString:@"destination"]) 
    {

        //NSLog(@"found current conditions tag it reads %@",currentElement);
        tdest = [[NSMutableString alloc] init];
    }
    if ([elementName isEqualToString:@"departs_from"])
    {
        tfrom = [[NSMutableString alloc] init]; 
    }
    if ([elementName isEqualToString:@"time"])
    {
        ttime = [[NSMutableString alloc] init]; 
    }
    if ([elementName isEqualToString:@"cs_id"])
    {
        tid = [[NSMutableString alloc] init]; 
    }
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if ([currentElement isEqualToString:@"destination"])
    {
        [tdest appendString:string];
    }
    if ([currentElement isEqualToString:@"departs_from"])
    {
        [tfrom appendString:string];
    }
    if ([currentElement isEqualToString:@"time"])
    {
        [ttime appendString:string];
    }
    if ([currentElement isEqualToString:@"cs_id"])
    {
        [tid appendString:string];
    }
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([currentElement isEqualToString:@"destination"])
    {
        [ldestination addObject:tdest];
        [tdest release];
    }
    if ([currentElement isEqualToString:@"departs_from"])
    {
        [ldeparts_from addObject:tfrom];
        [tfrom release];
    }
    if ([currentElement isEqualToString:@"time"])
    {
        [ltime addObject:ttime];
        [ttime release];
    }
    if ([currentElement isEqualToString:@"cs_id"])
    {
        [lcs_id addObject:tid];
        [tid release];
    }
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    ldestination = [[NSMutableArray alloc] init];
    ldeparts_from = [[NSMutableArray alloc] init];
    ltime = [[NSMutableArray alloc] init];
    lcs_id = [[NSMutableArray alloc] init];
    carsharexml = [[NSMutableData alloc] init];

    [self fetchcarshares];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [connection release];

    [ldestination release];
    [ldeparts_from release];
    [ltime release];
    [lcs_id release]; ///
    [carsharexml release];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [ltime count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"carsharecell" owner:self options:nil];
    }

    // Configure the cell...
    cell=maincell;

    UILabel *from;
    UILabel *dest;
    UILabel *time;

    from = (UILabel *)[cell viewWithTag:4];
    dest = (UILabel *)[cell viewWithTag:5];
    time = (UILabel *)[cell viewWithTag:6];
    from.text=[ldeparts_from objectAtIndex:indexPath.row];
    dest.text=[ldestination objectAtIndex:indexPath.row];
    time.text=[ltime objectAtIndex:indexPath.row];
    return cell;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

-(void)fetchcarshares
{

    MyManager *sharedManager = [MyManager sharedManager];
    NSString *urlString = [NSString stringWithFormat:@"http://url/get.php?username=%@&password=%@",sharedManager.user,sharedManager.passw];

    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];

    connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];

}

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

-(void) connectionDidFinishLoading:(NSURLConnection *)conn
{
    NSString *xmlcheck = [[NSString alloc] initWithData:carsharexml encoding:NSUTF8StringEncoding];

    NSLog(@"%@",xmlcheck);

    [xmlcheck release];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData: carsharexml];
    [parser setDelegate:self];
    [parser parse];
    [parser release];

    [[self tableView] reloadData];
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 102;
}
#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}

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

@end

我在 .h 文件中只定义了一个属性。回答该问题的人似乎认为我出现双重错误的原因是我的变量没有 @property

我有很多与此几乎相同的代码,我没有遇到任何问题。

我的问题是

  1. 什么时候应该使用属性?
  2. 我应该在这里使用属性吗?为什么?

谢谢

最佳答案

从技术上讲,您只需要为旨在从其他类访问的值使用属性,但许多人发现对所有指针类型实例变量使用(保留的)属性更容易,这样保留会更加自动化。 (然后在dealloc中使用self.propertyName = xxx;符号进行设置,使用self.propertyName = nil;进行释放。)

是的,您可以“手动”执行保留和释放操作,但这样做非常乏味,而且在进行“快速编辑”时往往会搞砸。但是,您必须注意的一件事是将保留的(不仅仅是自动保留的)值(例如您的 alloc/init 值)分配给 self.xxx属性(property)。如果您不以某种方式减轻它,这将导致双重保留。

另一件事是,如果您不使用属性,则在释放 指针值后始终将其nil。这可以防止您意外使用已释放的值,并且可以防止您执行双重 release

(请注意,使用我上面描述的“懒惰”技术绝对不是“糟糕的编程”,而是“完美地”解决所有问题。大约 98% 的编程是调试,以及您可以做的任何事情来防止错误或让他们更容易找到是好的。)

(我还会注意到,您在上述代码中的问题似乎主要是您在释放它们之后没有nil tdest 等指针。而您的if 测试可能会检查指针在使用之前是否已被清空。)

已添加:请注意,以上内容适用于 ARC 之前的程序。使用 ARC,“规则”发生了重大变化。

关于iphone - 何时在 Objective-C 中使用属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8194281/

相关文章:

objective-c - 重命名 NSString 常量

c++ - 平台无关的 C++ DLL

iphone - 为什么addSubview是: not retaining the view?

iphone - 如何获取 NSFetchedResultsController/NSManagedObjectContext 的所有条目?

java - 写入 NSData (Objective-c) 的 NSUInteger 无法转换为整数 (Java)

iphone - AVAssetImageGenerator 提供旋转的图像

iphone - 我想用 uikit( Nib 或 Storyboard)设置 cocos3d,但我收到错误

iphone - iPhone SDK:使用coreAudio播放声音

iphone - iOS 失去联系?

ios - RKMappingresult 在带有 restkit 的 64 位 iPhone 中返回不同的结果