Reputation: 47
Before beginning, I thought I should let you all know that I'm a self-taught beginner with no formal background what so ever.
My Goal: To display parsed HTML data from www.3v3live.com into various views in my app.
General Plan for implementation: I will create a reusable method that I can call to parse different pages of the site. It will have three parameters, including: a url, an Xpath query, and a type of data (input as a string and converted into a class by the method). The method shall return the gathered data in the type of data (from third parameter) in an array.
My Errors: 1) "No known class method for selector 'parseData:::' 2) "No known class method for selector 'stringFromArray:'
My OutPut: none
My Attempts to fix the errors: 1) I've added them to the .h file and interface of .m 2) I've added in a protocol (recommended by an answer on here) 3) I've converted the methods to instance methods (and back) 4) I've cleaned and run the project
Note: The error is at the line in the "textSet" method towards the bottom, and the "makeSlideShow" and "getText" methods are the precursors to my new method that is erroring (the precursors errored too).
My Code (ignore comments):
(ViewController.h
#import <UIKit/UIKit.h>
@protocol dataParsingVC <NSObject>
+ (id) stringFromArray: (NSArray*) arr;
+ (id) parseData: (NSString*) urlS : (NSString*) path : (NSString*) typeOfDataToReturn;
@end
@interface ViewController : UIViewController <NSURLConnectionDataDelegate>
// Drop Down Menu Buttons
@property (weak, nonatomic) IBOutlet UIButton *scheduleButton;
@property (weak, nonatomic) IBOutlet UIButton *newsButton;
@property (weak, nonatomic) IBOutlet UIButton *photosButton;
@property (weak, nonatomic) IBOutlet UIButton *docsButton;
@property (weak, nonatomic) IBOutlet UIButton *stagesButton;
@property (weak, nonatomic) IBOutlet UIButton *faqsButton;
@property (weak, nonatomic) IBOutlet UIButton *resultsButton;
@property (weak, nonatomic) IBOutlet UIButton *contactButton;
@property (weak, nonatomic) IBOutlet UIButton *finderButton;
- (IBAction)menuButton:(UIBarButtonItem *)sender;// Menu Button Open & Close
// WV = Web View; use as few as possible
@property (weak, nonatomic) IBOutlet UIWebView *hostATournamentWV; // for the poll
// SV = scroll view
@property (weak, nonatomic) IBOutlet UIScrollView *menuSV;
@property (weak, nonatomic) IBOutlet UIScrollView *homeSideTabsSV;
// Slide Show Image View
@property (weak, nonatomic) IBOutlet UIImageView *ssIV;
// TV = text view
@property (weak, nonatomic) IBOutlet UITextView *skillLevelsTV;
@property (weak, nonatomic) IBOutlet UITextView *homeTV;
@property (weak, nonatomic) IBOutlet UITextView * rulesTV;
// CV = container view
@property (weak, nonatomic) IBOutlet UIView *sideTabsCV;
// Arrays
@property (weak,nonatomic) NSMutableArray * _ssImagesArray;
@property (weak,nonatomic) NSMutableArray * _textArray;
// Error handling
@property (strong, nonatomic) NSMutableData * _responseData; // got warning in .m when prop was weak
// parsing related methods
+ (id) parseData: (NSString*) urlS : (NSString*) path : (NSString*) typeOfDataToReturn;
+ (id) stringFromArray: (NSArray*) arr;
@end
ViewController.m
#import "ViewController.h"
#import "TFHpple.h"
#import "TFHppleElement.h"
@interface ViewController ()
+ (id) parseData:(NSString *)urlS :(NSString *)path :(NSString *)typeOfDataToReturn;
+ (id) stringFromArray:(NSArray *)arr;
@end
@implementation ViewController
@synthesize _responseData;
@synthesize menuSV;
@synthesize homeSideTabsSV;
@synthesize homeTV;
@synthesize ssIV;
@synthesize hostATournamentWV;
@synthesize rulesTV;
@synthesize skillLevelsTV;
@synthesize _ssImagesArray;
@synthesize _textArray;
@synthesize scheduleButton;
@synthesize newsButton;
@synthesize photosButton;
@synthesize docsButton;
@synthesize stagesButton;
@synthesize faqsButton;
@synthesize resultsButton;
@synthesize contactButton;
@synthesize finderButton;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction) menuButton:(UIBarButtonItem *)sender {// When Drop Down Menu is pressed
//self.menuSV.contentSize = CGSizeMake(160, 160); // Make it so Scroll View (contains buttons) can scroll
if (self.homeSideTabsSV.hidden) // if buttons aren't showing, then uncover them
{
self.homeSideTabsSV.hidden = false;
} else if (self.homeSideTabsSV.hidden == false) // else (they're showing) hide them
{
self.homeSideTabsSV.hidden = true;
}
}
+ (id) stringFromArray : (NSArray *) arr // creates a string when given an array
{
NSString * result = [arr description];
return result;
}
+ (id) parseData: (NSString*) urlS : (NSString*) path : (NSString*) typeOfDataToReturn
{
// Set up request
NSURL * url = [NSURL URLWithString:urlS];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSURLResponse * response = nil;
NSError * error = nil;
// Send request
NSData * gatheredData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error) {return error;}
// set up parser
TFHpple * Parser = [TFHpple hppleWithHTMLData:gatheredData];
// Parse data
NSArray * Nodes = [Parser searchWithXPathQuery:path];
// Set up array to be returned
NSMutableArray * array = [[NSMutableArray alloc]initWithCapacity:0];
// Insert parsed data into "array"
for (TFHppleElement * element in Nodes)
{
// tell returned data it's class
id dataType = NSClassFromString(typeOfDataToReturn);
id returnedData = [[dataType alloc] init];
// set returnedData's value and insert it into "array"
returnedData= [[element firstChild] content];
[array addObject:returnedData];
}
return array;
}
- (void) textSet // setText already exists, so this one is textSet
{
// set homeTV's text = the string form (from "stringFromArray") of the array from "parseData"
[self.homeTV setText:[NSString stringFromArray:[ NSArray parseData: @"http://www.3v3live.com" : @"//p" : @"NSString"]]];
}
// call method with url & path to get text
- (id) getText:(NSURL*) url :(NSString*) path
{
NSData * gatheredText = [NSData dataWithContentsOfURL:url];
TFHpple * textParser = [TFHpple hppleWithHTMLData: gatheredText];
NSArray * textNodes = [textParser searchWithXPathQuery:path];
NSMutableArray * textArray = [[NSMutableArray alloc]initWithCapacity:0];
for (TFHppleElement * element in textNodes)
{
NSString * text = [[element firstChild] content]; // set text's value
[textArray addObject:text]; // add text to textArray
}
int z = [_textArray count]; // set z = end of _textArray
NSRange range = NSMakeRange(z, [textArray count]); // make a range from z to end of textArray
NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange:range]; // make an indexSet from range
[_textArray insertObjects:textArray atIndexes:indexSet]; // insert new parsed info at end of _textArray
return textArray;
}
- (void) makeSlideShow { // gets images for Slide Show
NSURLRequest * imagesURL = [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://www.3v3live.com"]]; // request connection
NSURLResponse * response = nil;
NSError * error = nil;
NSData * gatheredImages = [NSURLConnection sendSynchronousRequest:imagesURL returningResponse:&response error:&error];// get raw data
if (error == nil)
{
// Parse data here
TFHpple *imageParser1 = [TFHpple hppleWithHTMLData:gatheredImages]; // parses for almost all images in slide show
TFHpple *imageParser2 = [TFHpple hppleWithHTMLData:gatheredImages]; // parses for displayed image
NSString * parsePath1 = @"//div[@class ='newsSlideShow-article']"; // not shown pics path
NSString * parsePath2 = @"//div[@class = 'newsSlideShow-article current']"; // shown pic path
NSArray * Nodes = [imageParser1 searchWithXPathQuery:parsePath1]; // not shown pics array
NSArray * currentArticleArray = [imageParser2 searchWithXPathQuery:parsePath2]; // stores shown image
UIImage * currentArticle = [currentArticleArray objectAtIndex:0]; // displayed image in slide show should be first in the above array
[_ssImagesArray addObject:currentArticle ]; // add in displayed pic
int x = 1;
for (TFHppleElement * element in Nodes)// seperate collected data into pics; inserts rest of pics into imagesArray
{
x++;
UIImage * image = [UIImage imageWithData:[NSURL URLWithString:[element objectForKey:@"href"]]]; // set image's value
[_ssImagesArray addObject:image]; // add it to imagesArray
}
}
};
int j = 1; // counter for loopSlideShow
- (void) loopSlideShow // runs the slide show with gathered images from createSlideShow
{
int delayTime = 5; // how long each pic is shown
while (self.ssIV) // while the slideShowPic exists
{
if (j == [_ssImagesArray count]) // if it's reached the last pic, loop back to beggining of Slide Show
{
j = 1;
} else // else go on to next pic
{
j++;
};
[ssIV setImage:[_ssImagesArray objectAtIndex:j]]; // tell slide show which pic to display
[self performSelector:@selector(loopSlideShow) withObject:self afterDelay:delayTime]; // show each picture for X seconds
}
};
@end
Upvotes: 0
Views: 4906
Reputation: 38728
It looks like -[ViewController parseData:::]
is actually a method on ViewController
so it will not make sense if you call it on NSArray
If you keep it as a class method then you should call it with
[self.class parseData: @"http://www.3v3live.com" : @"//p" : @"NSString"]
or change it to an instance method and call it with
[self parseData: @"http://www.3v3live.com" : @"//p" : @"NSString"]
Either way this is a really poorly named method and it seems like some fundamental object oriented programming concepts are missing. Apple have some really good resources on getting started with Objective-C and iOS development.
Upvotes: 1