NSMutableArray возвращает значение null?

#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:

Было бы полезно добавить больше кода, но вот несколько предложений:

  1. Проверьте, startUploads вызывается ли перед загрузкой представления. Представление будет загружено только при первом обращении к нему для добавления в супервизор.

  2. Рассмотрите возможность инициализации processList в вашем init методе вместо viewDidLoad как для решения # 1, так и для того, чтобы представление могло загружаться и выгружаться iOS независимо от жизненного цикла ViewController (в зависимости от того, какие другие представления вы отображаете и возникают ли какие-либо предупреждения о памяти).

  3. Убедитесь, что вы выпускаете 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 месяцев. Я просмотрел все, и я все еще не могу найти лекарство от этого. Помещаю ли я его в представление, которое я загружаю, или в представление, из которого оно загружается? Не могли бы вы также предоставить какой-нибудь пример кода, если это не слишком сложно. Спасибо!