If-Then statement confusion, NSURL result not working quite right - iphone

What I would like to do is take the [self getYear] method which is predefined and returns an NSString in the form of a year (i.e. 1995), and then take that number and match it to which year it actually is, and set that to a URL variable, theClassyear. When this project is run, i have this as part of a setup method in -viewWillAppear and when I pull up the view (this is in a tab bar controller fyi) then I get either an NSURL error 101 or error -999. The [self getYear] method takes it's string from a NSUserDefaults string that is set by a UIPicker in a different view pushed by the controller. Like I said, when I first open the view and this method runs I get the correct result from the first NSLog, but then it runs through my if statements and ends up using the else statement which sets my NSURL that is supposed to be returned to null (according to my NSLog). Later on in the code I have another NSLog that prints the [self getYear] result again and that gives me the right number also. somehow my if-then logic is not running through correctly and I would love advice on what I may be doing wrong. Thanks in advance!!! :)
-(NSURL *)theClassYear{
NSURL *theClassYear = [[NSURL alloc] init];
NSLog(#"the user default loaded for the year is: %#",[self getYear]);
if ([self getYear] == #"1995") {
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=35443264449"];
}
else if ([self getYear] == #"1996"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=50371222704"];
}
else if ([self getYear] == #"1997"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=101880069858690"];
}
else if ([self getYear] == #"1998"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=98761155252"];
}
else if ([self getYear] == #"1999"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=34955119113"];
}
else if ([self getYear] == #"2000"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=41438241821"];
}
else if ([self getYear] == #"2001"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=44108047608"];
}
else if ([self getYear] == #"2002"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=98700780436"];
}
else if ([self getYear] == #"2003"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=36811255052"];
}
else if ([self getYear] == #"2004"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=40331531709"];
}
else if ([self getYear] == #"2005"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=97724430117"];
}
else if ([self getYear] == #"2006"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=50868469971"];
}
else if ([self getYear] == #"2007"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=38506528654"];
}
else if ([self getYear] == #"2008"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=55466866222"];
}
else if ([self getYear] == #"2009"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=105187085612"];
}
else if ([self getYear] == #"2010"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=39303927757"];
}
else if ([self getYear] == #"2011"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=281837582821"];
}
else if ([self getYear] == #"2012"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=79162636609"];
}
else if ([self getYear] == #"2013"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/home.php?sk=group_161338720557447"];
}
else if ([self getYear] == #"2014"){
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/home.php?sk=group_125352334187406"];
}
else {
NSLog(#"no matches");
}
NSLog(#"the url for the year you chose is: %#",theClassYear);
return theClassYear;
[theClassYear release];
}

More on my comment above
Put this data in a plist, grab the plist (which will be an NSDictionary called dict in this case) and then return [NSURL URLWithString:[dict objectForKey:[self getYear]]];

When you use == on objects such as NSString in Objective-C, you are not comparing the values of the objects, but the memory address of the object.* If you have two strings, and you want to see whether their contents are the same, you must, as Mahesh mentioned, use isEqualToString:, which does the correct comparison.
There are a couple of other things that can improved in your code. First, you are leaking an NSURL. You first create one with
NSURL *theClassYear = [[NSURL alloc] init];
and then you ignore it and create another one in one of the branches of your if:
theClassYear = [NSURL URLWithString:#"http://www.facebook.com/group.php?gid=35443264449"];
// This creates a new NSURL instance and leaks the old one.
To fix this, simply remove the initial assignment and make it a declaration:
NSURL * theClassYear; // You will assign to this name later, in a branch
Next, as Mahesh also pointed out, once you say return in a method, nothing past that line gets executed, so your [theClassYear release] does not occur. In this case, it's actually unnecessary, too.** The object that you get back from URLWithString: is autoreleased, which in this case is exactly what you want.
Finally, please do take Rexeisen's advice about putting all those strings into a dictionary. It will make your code much easier to read and more maintainable.
*Unlike interpreted languages such as Python, Perl, or PHP, or compiled languages with operator overloading such as C++.
**In fact, if it were running it would cause a crash due to overreleasing.

Related

Javascript Youtube API: buffering for ever - UIWebView iOS

I am using the YouTube API in UIWebView.
I have created a NSString with the HTML5 player that I load in the UIWebView. Everything works perfectly on iPhone 5 and iPad.
But, if I test the app using an iPhone 4, the player returns the buffering state all the time. Only if I explicitly press the play button, the player starts playing, without stopping again for buffering. It seems that although the video has been buffered, the player still gives me this state.
Is anyone aware of this problem? Any idea?
Thank you very much in advance!!
In LBYouTubePlayerViewController.m file
Replace Following method on yr old Method....
then test...
-(NSURL*)_extractYouTubeURLFromFile:(NSString *)html error:(NSError *__autoreleasing *)error {
NSString *JSONStart = nil;
// NSString *JSONStartFull = #"ls.setItem('PIGGYBACK_DATA', \")]}'";
NSString *JSONStartFull = #"bootstrap_data = \")]}'";
NSString *JSONStartShrunk = [JSONStartFull stringByReplacingOccurrencesOfString:#" " withString:#""];
if ([html rangeOfString:JSONStartFull].location != NSNotFound)
JSONStart = JSONStartFull;
else if ([html rangeOfString:JSONStartShrunk].location != NSNotFound)
JSONStart = JSONStartShrunk;
if (JSONStart != nil) {
NSScanner* scanner = [NSScanner scannerWithString:html];
[scanner scanUpToString:JSONStart intoString:nil];
[scanner scanString:JSONStart intoString:nil];
NSString *JSON = nil;
[scanner scanUpToString:#"}\";" intoString:&JSON];
JSON = [NSString stringWithFormat:#"%#}",JSON]; // Add closing bracket } to get vallid JSON again
// [scanner scanUpToString:#"\");" intoString:&JSON];
JSON = [self _unescapeString:JSON];
NSError* decodingError = nil;
NSDictionary* JSONCode = nil;
// First try to invoke NSJSONSerialization (Thanks Mattt Thompson)
id NSJSONSerializationClass = NSClassFromString(#"NSJSONSerialization");
SEL NSJSONSerializationSelector = NSSelectorFromString(#"dataWithJSONObject:options:error:");
if (NSJSONSerializationClass && [NSJSONSerializationClass respondsToSelector:NSJSONSerializationSelector]) {
JSONCode = [NSJSONSerialization JSONObjectWithData:[JSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&decodingError];
}
else {
JSONCode = [JSON objectFromJSONStringWithParseOptions:JKParseOptionNone error:&decodingError];
}
if (decodingError) {
// Failed
*error = decodingError;
}
else {
// Success
NSDictionary *dict = [JSONCode objectForKey:#"content"];
NSDictionary *dictTemp = [dict objectForKey:#"video"];
NSArray* videos = [dictTemp objectForKey:#"fmt_stream_map"];
NSString* streamURL = nil;
if (videos.count) {
NSString* streamURLKey = #"url";
if (self.quality == LBYouTubePlayerQualityLarge) {
streamURL = [[videos objectAtIndex:0] objectForKey:streamURLKey];
}
else if (self.quality == LBYouTubePlayerQualityMedium) {
unsigned int index = MAX(0, videos.count-2);
streamURL = [[videos objectAtIndex:index] objectForKey:streamURLKey];
}
else {
streamURL = [[videos lastObject] objectForKey:streamURLKey];
}
}
if (streamURL) {
return [NSURL URLWithString:streamURL];
}
else {
*error = [NSError errorWithDomain:kLBYouTubePlayerControllerErrorDomain code:2 userInfo:[NSDictionary dictionaryWithObject:#"Couldn't find the stream URL." forKey:NSLocalizedDescriptionKey]];
}
}
}
else {
*error = [NSError errorWithDomain:kLBYouTubePlayerControllerErrorDomain code:3 userInfo:[NSDictionary dictionaryWithObject:#"The JSON data could not be found." forKey:NSLocalizedDescriptionKey]];
}
return nil;
}

iOS GameCenter Matchmaker not working

I’m trying to make a custom matchmakingview using a matchmaker. The code below is used to find a match.
When i run this on two different devices with different Game Center accounts, both will get a match but none will connect to the match. They will just get stuck in the while loop in infinity and never get out. Have i missed something, do you need to call something to actually connect to the match?
- (void) findMatch{
GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
request.playersToInvite = nil;
NSLog(#"Start searching!");
[matchmaker findMatchForRequest:request
withCompletionHandler:^(GKMatch *match, NSError *error)
{
if (error) {
// Print the error
NSLog(#"%#", error.localizedDescription);
}
else if (match != nil)
{
curMatch = match;
curMatch.delegate = self;
NSLog(#"Expected: %i", match.expectedPlayerCount);
while (match.expectedPlayerCount != 0){
NSLog(#"PLayers: %i", curMatch.playerIDs.count);
}
NSLog(#"Start match!");
}
}];
You should not be using a while loop to wait for expectedPlayerCount to reach 0, instead implement the GKMatchDelegate method:
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
if (!self.matchStarted && match.expectedPlayerCount == 0) {
self.matchStarted = YES;
//Now you should start your match.
}
}

Using the YouTube API and iPhone SDK, how would I get information about a search result?

I'm trying to simply search for videos using a query, which is working perfectly using the below code.
// Create a service object for executing queries
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
// Services which do not require sign-in may need an API key from the
// API Console
service.APIKey = #"AIzaSy...";
// Create a query
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id,snippet"];
query.maxResults = 10;
query.q = searchBar.text;
query.videoEmbeddable = #"true";
query.type = #"video";
//query.country = #"US";
// Execute the query
GTLServiceTicket *ticket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
// This callback block is run when the fetch completes
if (error == nil) {
GTLYouTubeSearchListResponse *products = object;
[videoArray removeAllObjects];
// iteration of items and subscript access to items.
for (GTLYouTubeSearchResult *item in products) {
NSMutableDictionary *dictionary = [item JSONValueForKey:#"id"];
NSLog(#"%#", [dictionary objectForKey:#"videoId"]);
YoutubeVideo *video = [[YoutubeVideo alloc]init];
[video setLblTitle:item.snippet.title];
//Get youtube video image
[video setImgIconURL:[NSURL URLWithString:item.snippet.thumbnails.defaultProperty.url]];
[video setLblVideoURL:[dictionary objectForKey:#"videoId"]];
[video setLblChannelTitle:item.snippet.channelTitle];
[videoArray addObject:video];
}
reloadData = YES;
[tableView reloadData];
//Download images asynchronously
[NSThread detachNewThreadSelector:#selector(downloadImages)
toTarget:self
withObject:nil];
}else{
NSLog(#"Error: %#", error.description);
}
}];
However, now I'd like to display certain information about the video. Some of this information I can get out of
item.snippet
But I also need to get the video duration, and number of views. How can I get them using Youtube API 3.0?? I also had an idea to try using GData just for this, but it literally triples the load time to use
NSString *JSONString = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://gdata.youtube.com/feeds/api/videos/%#?v=2&alt=json", [video lblVideoURL]]] encoding:NSUTF8StringEncoding error:nil ];
How do I get the duration of the video, plus the number of views the video has?
Search query only accept ID and Snippet as parts. If you change to Video List Query you can include other parts, but you have to use one of the filters.
I think you'll have to get the video ID with the search query and do another query (Now a video query) filtering by ID (the Id you got), than you can get all other information of the videos you searched.
The problem is i'm having trouble getting the video ID, i think the API use the word "identifier" instead of "id" because it's a reserved word of objective-c.
Edit: Yeah, it was just a matter of time, just request my GTLYoutubeSearchResponse.JSON, an manipulated it as i wanted.
FIRST QUERY:
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id,snippet"];
query.maxResults = 10;
query.q = #"iphone";
query.fields = #"items(id,snippet)";
query.order = #"viewCount";
//query.channelId = #"UCsnbNwitAF9BzjjdMfRyK2g";//Kavaco
[appDelegate.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error == nil) {
appDelegate.videos = object;
[self performSegueWithIdentifier:#"videoList" sender:self];
}
else {
NSLog(#"%#", error.description);
}
}];
SECOND QUERY: In my TableViewController, inside my cellForRowAtIndexPath i do another query for each video i found. Be sure to request only the variables you need to avoid spending your credits, in my case i requested only viewCount.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myCell" forIndexPath:indexPath];
GTLYouTubeVideo *video = appDelegate.videos[indexPath.row];
NSMutableDictionary *videoIdJson = [video.JSON objectForKey:#"id"];
NSString *videoId = [videoIdJson objectForKey:#"videoId"];
cell.textLabel.text = video.snippet.title;
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosListWithPart:#"statistics"];
query.identifier = videoId;
query.maxResults = 1;
query.fields = #"items/statistics(viewCount)";
[appDelegate.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
id object,
NSError *error) {
if (error == nil) {
GTLYouTubeVideoListResponse *detalhe = object;
NSMutableDictionary *responseJSON = detalhe.JSON;
NSArray *tempArray = [responseJSON objectForKey:#"items"];
NSMutableDictionary *items = tempArray[0];
NSMutableDictionary *statistics = [items objectForKey:#"statistics"];
_views = [[NSString alloc] initWithFormat:#"Views: %#",[statistics objectForKey:#"viewCount"]];
cell.detailTextLabel.text = _views;
}
else {
NSLog(#"%#", error.description);
}
}];
cell.detailTextLabel.text = _views;
return cell;
}
Hope it helps.
Collect the id from search API and do another video list API call is the proper way to do what you want to achieve. The video list API call can put multiple video ids separate by comma in the same call. The extra call shouldn't consider exhausting because this is expected behavior on API v3:
Project Member #1 je...#google.com
That's the expected behavior, and not likely to change. Since the
search.list() method can return channels, videos, and playlists, only
properties that make sense for all of those resource types are
returned in the search responses. If you need to obtain any other
properties, making a follow-up request to, e.g., videos.list() is
required. Note that you can pass in up to 50 video ids to
videos.list(), so you can effectively look up an entire page's worth
of search.list() results in a single video.list() call.
If you try https://developers.google.com/youtube/v3/docs/videos/list#try-it , you set contentDetails,statistics as the part, you should able to get the following result:
"contentDetails": {
"duration": "PT20M38S",
"dimension": "2d",
"definition": "hd",
"caption": "false",
"licensedContent": false
},
"statistics": {
"viewCount": "191",
"likeCount": "7",
"dislikeCount": "0",
"favoriteCount": "0",
"commentCount": "0"
}
PT20M38S means 20 minutes and 38 seconds, based on ISO 8601(http://en.wikipedia.org/wiki/ISO_8601)
The best way for make this is:
if (!service) {
service = [[GTLServiceYouTube alloc] init];
service.shouldFetchNextPages = YES;
service.shouldFetchInBackground = YES;
service.retryEnabled = YES;
service.APIKey = #"AIzaSyDSO2JPnM_r9VcDrDJJs_d_7Li2Ttk2AuU";
}
[youtubeList removeAllObjects];
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id"];
query.maxResults = 50;
query.q = withText;
query.fields = #"items(id)";
query.order = #"viewCount";
query.type = #"video";
// query.videoDuration = #"long";//any-long-medium-short
__block NSInteger incrementRequest = 0;
[service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error) {
NSLog(#"Error is!! = %#", error.localizedDescription);
return;
}
GTLYouTubeVideoListResponse *idsResponse = object;
for (GTLYouTubeVideoListResponse *videoInfo in object) {
[youtubeList addObject:videoInfo.JSON];
GTLQueryYouTube *query2 = [GTLQueryYouTube queryForVideosListWithIdentifier:[[videoInfo.JSON valueForKey:#"id"] valueForKey:#"videoId"] part:#"id,contentDetails,snippet,statistics"];
query2.maxResults = 1;
query2.fields = #"items(id,contentDetails,snippet,statistics)";
query2.order = #"viewCount";
[service executeQuery:query2 completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error) {
NSLog(#"Error is!! = %#", error.localizedDescription);
return;
}
GTLYouTubeVideoListResponse *detalhe = object;
for (NSMutableDictionary *tmpDict in youtubeList) {
if ([[[tmpDict valueForKey:#"id"] valueForKey:#"videoId"] isEqualToString:[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"id"]]) {
[tmpDict removeObjectForKey:#"id"];
//condition personal
if (![Utils parseISO8601TimeIsGrater30:[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"contentDetails"] valueForKey:#"duration"]]) {
BOOL isBlockedInUs = NO;
for (NSString *countryRestric in [[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"contentDetails"] valueForKey:#"regionRestriction"] valueForKey:#"blocked"]) {
if ([countryRestric isEqualToString:#"US"]) {
isBlockedInUs = YES;
break;
}
}
if (!isBlockedInUs) {
[tmpDict addEntriesFromDictionary:detalhe.JSON];
[tmpDict setValue:[[[[detalhe.JSON valueForKey:#"items"] objectAtIndex:0] valueForKey:#"snippet"] valueForKey:#"publishedAt"] forKey:#"publishedAt"];
} else {
[youtubeList removeObject:tmpDict];
}
} else {
[youtubeList removeObject:tmpDict];
}
break;
}
}
incrementRequest ++;
if ([idsResponse.items count] == incrementRequest) {
//Finish
[self.tableView reloadData];
}
}];
}
}];

iOS webpage doesn't load unless button is tapped twice

- (IBAction)saveButton:(id)sender
{
NSURL *yourURL = [NSURL URLWithString: webpageURLLabel.text ];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:yourURL];
if ([self checkURL] == YES) {
[webpagePreview loadRequest:request];
webpagePreview.scalesPageToFit = YES;
}
}
- (BOOL)checkURL
{
NSString *arrayOfStrings = [NSArray arrayWithObjects:#"http://", #"https://", nil];
NSString *stringToSearchWithin = webpageURLLabel.text;
BOOL found=NO;
for (NSString *s in arrayOfStrings)
{
if ([stringToSearchWithin rangeOfString:s].location != NSNotFound)
{
found = YES;
break;
} else
{
webpageURLLabel.text = [NSString stringWithFormat:#"http://%#", webpageURLLabel.text];
found = YES;
break;
}
}
return found;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
webpageTitleLabel.text = [webpagePreview stringByEvaluatingJavaScriptFromString:#"document.title"];
}
I debugged it and it looks like it is suppose to load. But for some reason, when you tap the button the first time, nothing happens.
If the user taps the button a second time, it works fine. Any suggestions?
Looks to me like the first time the button is clicked, webpageURLLabel.text may not have a valid URL, and so the request is not valid. Then when [self checkURL] is called, webpageURLLabel.text gets set to a valid URL, and so the next click works.
Maybe you should be calling -checkURL before you create the NSURLRequest?
There are also problems in checkURL. Note that it always returns YES. Inside the for loop is logic that reduces to:
if (some condition) {
found = YES;
break;
} else {
// Fix webpageURLLabel.text
found = YES;
break;
}
However, consider what happens if you have a valid entry that starts with #"https://". The first time through the loop the if condition fails and so #"http://" gets added to the front of the URL and you return. So #"https://valid.com" turns into #"http://https://valid.com". You need to move everything in the else outside the for loop and do it only if found is not true.

Comparing a string from the web

hey all, i'm trying to read a file on the web that says "this is a test" and i wanna compare it... so here's what i got:
NSError *error;
NSURL *theURL = [NSURL URLWithString:#"http://mysite.com/test.asp"];
NSString *test = [NSString stringWithContentsOfURL:theURL encoding:NSASCIIStringEncoding error:&error];
NSLog(#"%#",test); //prints the results.. .does work
if(test == "this is a test"){
NSLog(#"File read");
} else {
NSLog(#"Bad file");
}
What am i doing wrong here? I always get "Bad file" but i know it's pulling in the text. Thanks all
damien
You need to check for nil as well & use isEqualToString function for comparison.
if(test != nil){
if([test isEqualToString:#"this is a test"]) {
// equal
}
else{
// not equal
}
}
else{
NSLog(#"Bad file");
}
If you use ==, you'll be comparing two pointers. Use isEqual: like so:
if([test isEqual: #"this is a test"]) {
// equal
}else{
// not equal
}
Other than the 2 answer you can also use.
– caseInsensitiveCompare:
– localizedCaseInsensitiveCompare:
– compare:
– localizedCompare:
– compare:options:
– compare:options:range:
– compare:options:range:locale:
– localizedStandardCompare: