Несколько NSXMLParser получают "Плохой доступ" - PullRequest
0 голосов
/ 15 марта 2011

Я хочу прочитать HTML-файл с помощью этой команды:

parseHTML = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:[@"http://theurl.com"]];    
[parseHTML setDelegate:self];
[parseHTML parse];

в методе didStartElement. Я хочу остановить реальный анализатор после того, как он найдет указанную строку, и проанализировать новый сайт с такой информацией:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
    if(somethingfound)
    {
            [parseHTML abortParsing];
            parseHTML2 = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:[@"http://theurl.com" stringByAppendingString:product_link]]];
            [parseHTML2 setDelegate:self];
            [parseHTML2 parse];
    }
}

Я получаю нерегулярную ошибку:

Тема 1: Программа получила сигнал: "EXC BAD ACCESS"

Есть идеи?С уважением


Здравствуйте, Уолтер, спасибо за ваш комментарий, вот полная реализация: я надеюсь, что это помогает ...: - /

FirstViewController.h

#import <UIKit/UIKit.h>

@interface FirstViewController : UIViewController <ZBarReaderDelegate, NSXMLParserDelegate>{

    UIImageView *resultImage;
    UITextView *resultText;
    NSString *product_link;
    NSXMLParser *parseHTML;
    NSXMLParser *parseHTML2;

}
@property (nonatomic, retain) IBOutlet UIImageView *resultImage;
@property (nonatomic, retain) IBOutlet UITextView *resultText;
@property (nonatomic, assign) IBOutlet NSString *product_link;
@property (nonatomic, assign) NSXMLParser *parseHTML;
@property (nonatomic, assign) NSXMLParser *parseHTML2;
@property (nonatomic, retain) NSMutableArray *myMutableArray;

- (IBAction) scanButtonTapped;

@end

FirtViewController.m

#import "FirstViewController.h"
#import "/System/Library/Frameworks/Foundation.framework/Headers/NSDebug.h"

@implementation FirstViewController


@synthesize resultImage, resultText;
@synthesize product_link;
@synthesize parseHTML, parseHTML2;


bool link_is_here = false;
bool allergy_is_here = false; 
bool parse_one_ok = true;
int hoch = 0;


- (IBAction) scanButtonTapped
{
    NSZombieEnabled = true;

    // ADD: present a barcode reader that scans from the camera feed
    ZBarReaderViewController *reader = [ZBarReaderViewController new];
    reader.readerDelegate = self;

    ZBarImageScanner *scanner = reader.scanner;
    // TODO: (optional) additional reader configuration here

    // EXAMPLE: disable rarely used I2/5 to improve performance
    [scanner setSymbology: ZBAR_I25
                   config: ZBAR_CFG_ENABLE
                       to: 0];

    // present and release the controller
    [self presentModalViewController: reader animated: YES];
    [reader release];
}

- (void) imagePickerController: (UIImagePickerController*) reader
 didFinishPickingMediaWithInfo: (NSDictionary*) info
{

    // ADD: get the decode results
    id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
    ZBarSymbol *symbol = nil;
    for(symbol in results)
        break;

    // EXAMPLE: do something useful with the barcode data
    resultText.text = symbol.data;
    parseHTML = [[[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:[@"http://URL.de/suche/?q=" stringByAppendingString:symbol.data]] ]autorelease];
    [parseHTML setDelegate:self];
    [parseHTML parse];

//    [parseHTML release];

    // EXAMPLE: do something useful with the barcode image
    resultImage.image =
    [info objectForKey: UIImagePickerControllerOriginalImage];

    // ADD: dismiss the controller (NB dismiss from the *reader*!)
    [reader dismissModalViewControllerAnimated: YES];
}


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
    for(NSString *key in [attributeDict allKeys]) {
        if ([[attributeDict valueForKey:key] isEqualToString:@"some_string"]) {
            link_is_here = true;        
        }
        if ([key isEqualToString:@"href"] && link_is_here) {
            product_link = [attributeDict valueForKey:key];

//            [parseHTML abortParsing];

            parseHTML2 = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:[@"http://URL.de" stringByAppendingString:product_link]]];
            [parseHTML2 setDelegate:self];
            [parseHTML2 parse];
            parse_one_ok = true;
            link_is_here = false;
        }
        if ([key isEqualToString:@"id"] && [[attributeDict valueForKey:key] isEqualToString:@"other_string"]) {
            allergy_is_here = true;
        }
        if ([key isEqualToString:@"title"] && allergy_is_here) {      
            NSLog(@"DO:  %@",[attributeDict valueForKey:key]);  
        }
        if ([key isEqualToString:@"id"] && [[attributeDict valueForKey:key] isEqualToString:@"string"]) {
            allergy_is_here = false;

            parse_one_ok = true;
            NSLog(@"Parser off");
            //close all parser
        }
     }
}
-(void) parserDidEndDocument:(NSXMLParser *)parser{
    [parseHTML setDelegate:nil];
    [parseHTML2 setDelegate:nil];
    [parseHTML release];
    if (parse_one_ok) {

        [parseHTML2 release];
    }
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [parseHTML release];
    [parseHTML2 release];
    self.product_link = nil;
    self.resultImage = nil;
    self.resultText = nil;
    [super dealloc];
}

@end

эй, мое объявление находится в заголовке:

@interface FirstViewController : UIViewController <NSXMLParserDelegate>{
    NSString *product_link;
    NSXMLParser *parseHTML;
    NSXMLParser *parseHTML2;
}
@property (nonatomic, retain) IBOutlet NSString *product_link;
@property (nonatomic, retain) NSXMLParser *parseHTML;
@property (nonatomic, retain) NSXMLParser *parseHTML2;

и в источнике:

@synthesize parseHTML, parseHTML2;
@synthesize product_link;

я получаю в консоли следующие исключения:

- [NSCFString setDelegate:]: нераспознанный селектор, отправленный экземпляру 0x1acad0

1 Ответ

1 голос
/ 15 марта 2011

Когда мне нужно разобрать два файла одновременно, я настраиваю второго делегата для второго файла.Делегат - это простой объект NSO, который придерживается протокола NSXML Parser Delegate.(У него есть parserDidStart, parserDidEnd, бла-бла-бла).

Затем в моем didEndElement моего первого парсера я запускаю второй парсер с чем-то вроде этого

SoundCloudParser *scParser = [[[SoundCloudParser alloc] init]autorelease];
NSOperationQueue *queue = [[[NSOperationQueue alloc] init]autorelease];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:scParser selector:@selector(parseXMLUrl:) object:currentArticle.uriString];
[queue addOperation:operation];
[operation release];  

Я делаю это в отдельном потоке, поэтому у вас есть очередь втам.Мой parseXMLUrl: looks just like a regular one, it just sets the delegate to my second delegate object instead of setting it to self`.

Еще одна вещь, о которой вы должны подумать, это то, что вы работаете в didStartElement, и я обнаружил, что часто у меня нет никаких значенийв моих переменных синтаксического анализа, пока я не доберусь до didEndElement.Это было бы чем-то еще для вас, чтобы проверить.

ОБНОВЛЕНИЕ: В будущем, если вы пытаетесь построить что-то вроде ZBarSDK или другого проекта, пожалуйста, так и скажите.Это позволило бы мне сэкономить около получаса с вашим кодом.
По сути, нам нужно создать нового делегата.Давайте назовем это newDelegate.Настройте его как обычный объект NSO и заставьте его следовать протоколу <NSXMLDelegate>.Ему нужен mutableArray или словарь для хранения данных, которые он будет анализировать, и ему нужна функция для его запуска.И это все.
Итак, давайте предположим, что вы создали newDelegate.h и newDelegate.m в своем проекте и в newDelegate.h, у вас есть #import "Your_App_Delegate.h" @interface newDelegate: NSObject {

NSMutableString *currentElement;
NSMutableArray *currentArticle;
}

- (void)parseXMLUrl:(NSString *)URL;
@end

Итак, теперь в вашем didStartElement вы бы назвали newDelegate следующим образом:

newDelegate *ndParser = [[[newDelegateParser alloc] init]autorelease];
NSOperationQueue *queue = [[[NSOperationQueue alloc] init]autorelease];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:ndParser selector:@selector(parseXMLUrl:) object:[NSString stringWithFormat:@"http://URL.de/%@",product_link]];
[queue addOperation:operation];
[operation release];    

Это запустит второй парсер и передаст ему URL для разбора.Вам понадобится способ получить эти данные, поэтому либо сохраните некоторые результаты в вашем делегате приложения, либо измените метод parseXMLURL второго анализатора, чтобы он возвращал какое-то значение.

...