#iphone #objective-c #cocoa-touch
#iPhone #objective-c #cocoa-touch
Вопрос:
У меня есть UITableView, который заполняется моим NSMutableArray. Вот как я это настроил в my .h
@interface processViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
NSMutableArray *processList;
}
@property (copy, readwrite) NSMutableArray *processList;
и мой .m
@synthesize processList;
-(void)viewDidLoad {
processList = [[NSMutableArray alloc] init];
}
Я поместил на него NSLog в viewDidLoad, и он отображается просто отлично. Но после того, как я выполняю действие, processList
массив возвращается null
. Есть идеи, почему?
Спасибо
Коултону
РЕДАКТИРОВАТЬ 1:
- (void)startUploads {
// Start UIActivity in the top
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// Start Pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Display results for testing purposes (commented out)
NSArray *resultstwo = [database executeQuery:@"SELECT * FROM processes"];
for (NSDictionary *rowtwo in resultstwo) {
// Get ID
int getUserIDcount = 0;
NSArray *getUserIDInfo = [database executeQuery:@"SELECT * FROM login"];
for (NSDictionary *getUserIDRow in getUserIDInfo) {
getUserIDcount ;
NSString *oneUserID = [getUserIDRow valueForKey:@"id"];
theUserID = [NSString stringWithFormat:@"%@", oneUserID];
}
// If theUserID exists...
if (getUserIDcount == 0) {
//myTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector: @selector(checkLogin) userInfo: nil repeats: NO];
} else {
// Get URL of image
NSString *sqlImageUploadPathOne = @"./../Documents/";
NSString *sqlImageUploadPathTwo = [rowtwo valueForKey:@"image"];
NSString *getAlbumID = [rowtwo valueForKey:@"album"];
NSString *sqlImageUploadPath = [NSString stringWithFormat:@"%@%@",sqlImageUploadPathOne,sqlImageUploadPathTwo];
//testLabel.text = @"Uploading...";
// Display Image in UIImageView (uploadImageHidden)
UIImage *attemptImage = [UIImage imageNamed:sqlImageUploadPath];
[uploadImageHidden setImage:attemptImage];
// Upload to server
NSData *imageData = UIImageJPEGRepresentation(uploadImageHidden.image, 90);
NSString *urlStringOne = @"http://myflashpics.com/iphone_processes/upload.php?album=";
NSString *urlStringTwo = @"amp;id=";
NSString *urlString = [NSString stringWithFormat:@"%@%@%@%@",urlStringOne,getAlbumID,urlStringTwo,theUserID];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
NSString *boundary = [NSString stringWithString:@"---------------------------14737809831466499882746641449"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:contentType forHTTPHeaderField:@"Content-Type"];
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"rn--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name="userfile"; filename=".jpg"rn"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Type: application/octet-streamrnrn"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];
[body appendData:[[NSString stringWithFormat:@"rn--%@--rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
//NSLog(@"%@", returnString);
if ([returnString rangeOfString:@"yes"].location == NSNotFound) {
// Fail
} else {
// Delete image if successful
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *myFilePath = [documentsDirectoryPath stringByAppendingPathComponent:sqlImageUploadPathTwo];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:myFilePath error:NULL];
[database executeNonQuery:@"DELETE FROM processes WHERE image=?", sqlImageUploadPathTwo];
// Get Photo ID
NSArray *myWords = [returnString componentsSeparatedByString:@" "];
NSString *photoID = [myWords objectAtIndex:1];
NSString *usernameID = [myWords objectAtIndex:2];
NSString *defaultName = @"Photo uploaded from the flashpics iPhone application";
// Get Thumbnail URL
NSString *thumbnailURLOne = @"http://myflashpics.com/users/";
NSString *thumbnailURLTwo = @"/pictures/thumbnails/";
NSString *thumbnailURLThree = @".jpg";
NSString *thumbnailURL = [NSString stringWithFormat:@"%@%@%@%@%@",thumbnailURLOne,usernameID,thumbnailURLTwo,photoID,thumbnailURLThree];
// Download thumbnail
//NSLog(@"Downloading...");
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:thumbnailURL]]];
//NSLog(@"%f,%f",image.size.width,image.size.height);
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//NSLog(@"%@",docDir);
//NSLog(@"saving jpeg");
NSString *jpegFilePath = [NSString stringWithFormat:@"%@/%@_thumbnail.jpg",docDir,photoID];
NSData *data2 = [NSData dataWithData:UIImageJPEGRepresentation(image, 0.2f)];//1.0f = 100% quality
[data2 writeToFile:jpegFilePath atomically:YES];
//NSLog(@"saving image done");
[image release];
// Put in database
NSString *thumbnailEnd = @"_thumbnail.jpg";
NSString *thumbnailLocation = [NSString stringWithFormat:@"%@%@",photoID,thumbnailEnd];
int theCount = 0;
NSArray *getUserIDInfotoo = [database executeQuery:@"SELECT * FROM images WHERE id=?",photoID];
for (NSDictionary *getUserIDRowtoo in getUserIDInfotoo) {
theCount ;
}
if (theCount == 0) {
[database executeNonQuery:@"INSERT INTO images (id, name, thumbnail, album) VALUES (?, ?, ?, ?)", photoID, defaultName, thumbnailLocation, getAlbumID];
}
//[NSThread detachNewThreadSelector:@selector(updateImages) toTarget:RootViewController withObject:nil];
//myTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector: @selector(updateImages) userInfo: nil repeats: NO];
}
[request release];
[returnString release];
}
//NSLog([rowtwo valueForKey:@"image"]);
//NSLog([rowtwo valueForKey:@"album"]);
}
[pool release];
// Stop the UIActivity in the top bar
TableViewAppDelegate *dataCeter = (TableViewAppDelegate *)[[UIApplication sharedApplication] delegate];
if ([dataCeter.dataTen isEqualToString:@""]) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
}
Правка 2:
Где вызывается startUploads (different .m)
processViewController *processTable = [[processViewController alloc] initWithNibName:@"processView.xib" bundle:nil];
[processTable startUploads];
[processTable release];
Комментарии:
1. Что такое «действие»? Очень важно знать, что вы делаете в промежутке между временем, когда массив действителен, и временем, когда он недействителен.
2. @Marc Тег [cocoa] предназначен для Cocoa в Mac OS. Для iOS вместо этого используйте [cocoa-touch].
3. @Mark W: Только что опубликовал мой код, который происходит.
4. Не вижу, был ли установлен processList.
Ответ №1:
Было бы полезно добавить больше кода, но вот несколько предложений:
-
Проверьте,
startUploads
вызывается ли перед загрузкой представления. Представление будет загружено только при первом обращении к нему для добавления в супервизор. -
Рассмотрите возможность инициализации
processList
в вашемinit
методе вместоviewDidLoad
как для решения # 1, так и для того, чтобы представление могло загружаться и выгружаться iOS независимо от жизненного цикла ViewController (в зависимости от того, какие другие представления вы отображаете и возникают ли какие-либо предупреждения о памяти). -
Убедитесь, что вы выпускаете
processList
вdealloc
. Вам нужно освободить его только вviewDidUnload
случае, если он воссоздан и загружен вviewDidLoad
.
Ваш пример кода не показывает, когда startUploads
вызывается, и вы не добавляете никаких элементов в processList
, поэтому трудно сказать, актуально ли вышеуказанное. Опубликуйте еще немного кода, и я соответствующим образом пересмотрю свой ответ.
удачи!
[ПРАВКА: добавлен пример кода]
Опубликованные вами фрагменты кода не являются полной реализацией контроллера представления и связанных с ним объектов, которые взаимодействуют с ним. Учитывая код, который я видел, дизайн вашего приложения не соответствует шаблону проектирования MVC (модель / представление / контроллер), и я бы делал все немного по-другому. Однако я не хочу делать предположений о коде, которого я не видел, или о ваших конечных намерениях или способностях как разработчика. Я не могу написать ваше приложение для вас, просто пытаюсь напрямую помочь вам с конкретным вопросом, который вы задали относительно того, почему ваше свойство NSMutableArray остается нулевым после startUploads
завершения действия. Имея это в виду, вот мои правки к опубликованному вами коду:
processViewController.m — добавить следующее:
- (id)initWithNibNamed:(NSString *)nibName bundle:(NSBundle *)bundle {
self = [super initWithNibNamed:nibName bundle:bundle];
if (self) {
processList = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc {
self.processList = nil;
[super dealloc];
}
different.m
- (void)displayProcessVC {
ProcessViewController *processVC = [[ProcessViewController alloc] initWithNibNamed:@"processView.xib" bundle:nil];
NSLog(@"Different:displayProcessVC BEFORE STARTING UPLOAD, processList = %@", processVC.processList);
[processVC startUploads];
NSLog(@"Different:displayProcessVC AFTER STARTING UPLOAD, processList = %@", processVC.processList);
// would normally present process VC here
[processVC release];
}
Надеюсь, это поможет.
Комментарии:
1. хорошо, итак, мой ответ верен. ваша проблема выглядит как # 2. Вам нужно выделить
processList
вinitWithNibName:
, а не вviewDidLoad
. ПриstartUploads
вызове представление еще не загружено. Ваш пример не имеет особого смысла, поскольку вы инициализируете processTable и никогда не представляете его.processViewController
обычно они представляются модально или загружаются на навигационный контроллер перед выпуском.2. Хорошо, итак, если я сделаю это следующим образом:
processTable.processList = [[NSMutableArray alloc] init];
, это не сработает. Когда viewDidLoad открывается, он выводит NULL в консоль. Я также поместил его в свой,-(id)init { processList = [[NSMutableArray alloc] init]; }
и он не вызывается, когда когда-либоstartUploads
вызывается (поместите NSLog в инициализацию, и он не отображается, пока не откроется представление).3. Когда я сказал рассмотреть возможность инициализации processList в вашем методе init, я не имел в виду буквально
-(id)init
. В данном случае вы используете-(id)initWithNibName:
, поэтому вам нужно сделать это там. Переопределите реализацию суперкласса и инициализируйтеprocessList
там. Я рекомендую прочитать руководство по программированию контроллера View от Apple и, в частности, разделы, посвященные жизненному циклу контроллера View.4. Еще раз, извините за мои комментарии новичка. Я действительно просматривал и работал с Xcode только более 2 месяцев. Я просмотрел все, и я все еще не могу найти лекарство от этого. Помещаю ли я его в представление, которое я загружаю, или в представление, из которого оно загружается? Не могли бы вы также предоставить какой-нибудь пример кода, если это не слишком сложно. Спасибо!