RNs*_*ost 12 iphone properties objective-c ios
我在这里有一个问题: 在iPhone应用程序中混淆双重免费错误消息/内存泄漏,我认为需要一个新问题来回答它.
我感兴趣的代码就是那个问题,但我会在这里发布
#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
Run Code Online (Sandbox Code Playgroud)
我只在.h文件中定义了一个属性.回答这个问题的人似乎认为我有双重免费错误的原因是由于我没有@property我的变量.
我有很多代码几乎与此相同,我没有问题.
我的问题是
谢谢
Hot*_*cks 21
从技术上讲,您只需要为可以从其他类访问的值使用属性,但是许多人发现所有指针类型实例变量的使用(保留)属性更容易,因此保留更加自动化.(然后使用self.propertyName = xxx;符号进行设置和self.propertyName = nil;释放dealloc.)
是的,你可以"手动"进行保留和释放,但这样做很麻烦,当你进行"快速编辑"时,你往往会把事情弄糟.但是,您必须注意的一件事是将保留(不是简单的自动恢复)值(例如您的alloc/init值)分配给self.xxx属性.如果你不以某种方式缓解它,这将导致双重保留.
如果你不使用属性,另一件事就是nil在release它之后总是一个指针值.这可以防止您意外使用释放的值,并且可以防止您进行双重操作release.
(请注意,使用像我上面描述的"懒惰"技术并不是"糟糕的编程",而是"完美地"找出所有内容.大约98%的编程是调试,以及你可以采取的任何措施来防止错误或使它们更容易找到善良.)
(我还会注意到你在上面的代码中出现的问题似乎主要是你在发布它们之后没有nil这些tdest指针.而且你的if测试应该在使用之前检查指针是否已经被填满了.)
补充:请注意,上述内容适用于ARC之前的程序.随着ARC,"规则"发生了重大变化.
属性做了很多事情.在最肤浅的层面,它们允许您以点线形式访问您的成员变量.充其量,它们可以是出色的内存管理工具(以及更多).
假设你有一个变量:
NSNumber * myNumber;
Run Code Online (Sandbox Code Playgroud)
稍后在代码中,您可以访问它:
myNumber = [NSNumber numberWithInt: 5];
Run Code Online (Sandbox Code Playgroud)
问题是您可能会丢失对myNumber中先前存储的值的引用.可能的内存泄漏!! 此时,您没有在myNumber上保留,并且在您使用它之前可能会被取消删除.
物业如何帮助?假设你在它周围定义了一个属性并使用了synthesize:
在接口定义中:
NSNumber * myNumber;
...
@property (retain, nonatomic) NSNumber * myNumber;
Run Code Online (Sandbox Code Playgroud)
和
在实现文件中:
@synthesize myNumber;
Run Code Online (Sandbox Code Playgroud)
这将创建一个getter和setter.含义......每次将myNumber分配给某个东西时,如:
self.myNumber = newNumber;
Run Code Online (Sandbox Code Playgroud)
调用以下setter方法(由synthesize指令创建):
- (NSNumber *) setMyNumber: (NSNumber *) newNumber {
[myNumber release];
myNumber = newNumber;
[myNumber retain];
return newNumber;
}
Run Code Online (Sandbox Code Playgroud)
在这里,myNumber会自动获得保留.每次手工操作都非常繁琐......正如您所看到的,使用属性要容易得多.
不过,这仍然不是一个完美的解决方案!为什么?如果在实现中使用以下语句,该怎么办:
myNumber = newNumber;
Run Code Online (Sandbox Code Playgroud)
请记住,只有在使用带点的符号(self.myNumber)时才会调用属性的getter和setter .所以在这里,使用属性对我们没有任何作用,因为我们忘了使用它们!这是非常常见的,可能会失效并且理解为令人沮丧.
那么,最好的方法是什么?这是我推荐的(和无数其他人一样):
在接口类中:
NSNumber * _myNumber;
...
@property (retain, nonatomic) NSNumber * myNumber;
Run Code Online (Sandbox Code Playgroud)
在实现文件中:
@synthesize myNumber = _myNumber;
Run Code Online (Sandbox Code Playgroud)
现在,您可以访问您的号码:
self.myNumber = whateverNewNumber;
Run Code Online (Sandbox Code Playgroud)
但是,如果你这样做了:
myNumber = whateverNewNumber;
Run Code Online (Sandbox Code Playgroud)
您将收到错误...因为myNumber变量不存在...强迫您self.myNumber每次都使用!
此外,如果您确实选择了这条路线,请不要忘记dealloc:
- (void) dealloc {
[_myNumber release];
_myNumber = nil;
}
Run Code Online (Sandbox Code Playgroud)
或更简洁:
- (void) dealloc {
self.myNumber = nil;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3763 次 |
| 最近记录: |