I'm using Eric Czarny's Cocoa XML-RPC framework to make a call to the Wordpress API's. I've downloaded the sample app from Wordpress which gives some good examples. Unfortunately the good examples are for every call EXCEPT wp.newComment.
I'm trying to post a comment using the code below and I keep getting an error with a localized description that tells me to check my input parameters. I've checked and rechecked and I don't understand what is wrong.
Any ideas?
NSDictionary *commentStructure = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:0], #"comment_parent", #"xmlrpc anonymous comments plugin now enabled", #"content", #"Test Author", #"author", #"http://iphone.someurl.com", #"author_url", #"someemailaddy#hotmail.com", #"author_email", nil];
NSArray *args = [NSArray arrayWithObjects:[NSNumber numberWithInt:0], #"", #"", [NSNumber numberWithInt:[self.parentFeedItem.postID intValue]], commentStructure, nil]; // the param(s)
NSString *server = [[[NSString alloc] initWithString:#"http://www.someurl.com/xmlrpc.php"] autorelease]; // the server
NSString *method = [[[NSString alloc] initWithString:#"wp.newComment"] autorelease]; // the method
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithHost:[NSURL URLWithString:server]];
[request setMethod:method withObjects:args];
id response = [self executeXMLRPCRequest:request];
[request release];
if( [response isKindOfClass:[NSError class]] ) {
//return nil;
NSLog(#"There was a problem");
NSLog([response localizedDescription]);
}
I found that I had downloaded an older version of the example Wordpress source code which did not have an example for wp.newComment.
You can find a much newer version of the source code here which does have better examples.
http://iphone.trac.wordpress.org/browser
Using the examples from the newer code I was able to resolve my issues.
Related
- (BOOL)parserJSONString:(NSString *)jsonString error:(NSError **)anError {
//some data getting
//error handle
NSString *description = #"phone number couldn't be using";
NSString *recoverySuggestion = #"Please provide an other phone number.";
NSInteger errorCode = -1;
NSArray *keys = [NSArray arrayWithObjects: NSLocalizedDescriptionKey, NSLocalizedRecoverySuggestionErrorKey, nil];
NSArray *values = [NSArray arrayWithObjects:description, recoverySuggestion, nil];
NSDictionary *userDict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
*anError = [[NSError alloc] initWithDomain:#"my domain" code:errorCode userInfo:userDict];
return NO;
}
*anError = [[NSError alloc] initWithDomain:#"my domain" code:errorCode userInfo:userDict]; compiler give next leak warning
"Potential null dereference. According to coding standards in 'Creating and Returning NSError Objects' the parameter '' may be null"
How to fix this?
You need to first check whether anError is nil or NULL:
if (anError) {
*anError = [[NSError alloc] initWithDomain:#"my domain" code:errorCode userInfo:userDict];
}
This is not actually a leak warning, but a potential dereference of a null pointer. The compiler is complaining about the line
*anError = [[NSError alloc] initWithDomain:#"my domain" code:errorCode userInfo:userDict];
You assign to the location being pointed to by anError without checking, whether anError is actually the null pointer (which is allowed "according to the coding standard", and may happen, if the caller is not interested in detailed error information).
I have a method where I fetch GDataFeedBase entries and return these as an array to another function
NSMutableArray *tempFeedArray = [NSMutableArray array];
NSURL *feedURL = [[NSURL alloc] initWithString:escapedUrlString];
NSData *data = [NSData dataWithContentsOfURL:feedURL];
GDataFeedBase *feedBase = [[GDataFeedBase alloc] initWithData:data];
[tempFeedArray addObjectsFromArray:[feedBase entries]];
[feedURL release];
[feedBase release];
return tempFeedArray;
.....
I have another function where I retrieve required values from tempFeedArray object that is GDataEntryYouTubeVideo
for(int count = 0; count < loopCount; count ++){
NSMutableDictionary *feedBaseEntryDict = [[NSMutableDictionary alloc] init];
entry = [tempFeedArray objectAtIndex:count];
youTubeUrl = [[entry alternateLink] href];
if ([entry statistics]!= nil) {
noOfVws= [[[entry statistics] viewCount] intValue];
}
duratn = [[[entry mediaGroup] duration] stringValue];
descr = [[[entry mediaGroup] mediaDescription] stringValue];
authorName = [[[entry authors] objectAtIndex:0] name];
publishedDt = [[entry publishedDate] stringValue];
rating = [[[entry rating] average] stringValue];
imageURL = [[[[entry mediaGroup] mediaThumbnails] objectAtIndex:0] URLString];
videoTitle = [[[entry mediaGroup] mediaTitle] stringValue];
.....
}
......
For the first time everything works fine. But the next time, it shows memory leak at
GDataXMLNode stringFromXMLString:
Did anyone else face this issue?
I found similar issue raised in gdata developer forum:
http://groups.google.com/group/gdata-objectivec-client/browse_thread/thread/f88de5a7bb784719/cab328a8725ee6c5
but the solution doesn't solve the issue.
Any help is much appreciated.
Looks like it might not be your code but the client library there were a few other threads on the same issue. This one has a work around, but I have not tried it myself.
The other options you have would be to upgrade to latest version (1.12 was released on Apr 11th 2011), take a look at the source and try to track down your problem, or submit an issue (it looks like the project is still actively developed).
Since the code is "stealing" entries from the feed, leaving them pointing to their parent feed (rather than copying the entries, which would create independent versions) there may be an issue with the strings cache. Try disabling the cache by commenting out -addStringsCacheToDoc in GDataXMLNode.m
I need to convert data received from the web via an array in a PHP script into an array that I can pull values out of. Here's my code!
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
//NSString *payloadAsString = [NSString stringWithUTF8String:[receivedData bytes]];
NSArray *payloadAsString = [NSKeyedUnarchiver unarchiveObjectWithData:receivedData];
[payloadAsString finishEncoding];
verified = [payloadAsString objectAtIndex:0];
NSLog(#"logging");
//NSString *no = [[NSString alloc] init stringWithCString:verified];
NSLog(#"%#", verified);
if([verified isEqualToString:#"admin"]){
NSLog(#"test admin");
[self performSelector:#selector(changeViewAdmin) withObject:nil afterDelay:0.05];
}
if([verified isEqualToString:#"user"]){
NSLog(#"test user");
[self performSelector:#selector(changeView) withObject:nil afterDelay:0.05];
}
if([verified isEqualToString:#"No"]){
NSLog(#"test no");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Invalid UserName/Password combination!"
delegate:self
cancelButtonTitle:#"Okay"
otherButtonTitles:nil];
[alert show];
[alert release];
}
[payloadAsString release];
//NSLog(#"%#", verified);
// INSERT GOOGLE MAPS URL REQUEST HERE
/*if(requestType == 1){
NSString* addressText = payloadAsString;
// URL encode the spaces
addressText = [addressText stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding];
NSString* urlText = [NSString stringWithFormat:#"http://maps.google.com/maps?q=%#", addressText];
// lets throw this text on the log so we can view the url in the event we have an issue
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlText]];
// */
//
//}
[connection release];
self.receivedData = nil;
}
Unfortunately, my console returns null and asks if I've put the -finishencoding method in. Question is, if that's correct, where would I do so?
PS: Another question, is if I'm retrieving an array of data from a database, is a PHP script the best way to go? Thank you.
1) Of all this code the only string relevant to your question is
NSArray *payloadAsString = [NSKeyedUnarchiver unarchiveObjectWithData:receivedData];
I really doubt that PHP script returns you data in NSKeyedUnarchiver-compatible format. I believe the only reason you don't get NSInvalidArgumentException exception from this method is that receivedData is nil (did you initialize it anywhere?). Try to make a string from what you receive like this
[[[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding] autorelease]
and log it. From this I hope it will be clear how to parse response.
2) Do not name NSArray instances like 'blahBlahString'. Strings and arrays are completely different.
NSKeyedUnarchiver can only unarchive instances which are produced by instances of the NSKeyedArchiver class.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSKeyedUnarchiver_Class/index.html
No Matter what i do, i cannot get a post published to an application page wall (the app being logged into) via an iPhone application. I'm able to log in using FBLoginDialog and then retrieve data to populate a tableview, however when i click a button to publish some test content it doesn't work. Here is the button action:
- (void)compose:(id)sender;
{
NSString *tid=#"115372005166292";
NSString *body = #"My Test";
NSArray *obj = [NSArray arrayWithObjects:body,[NSString stringWithFormat:#"%#", tid],nil];
NSArray *keys = [NSArray arrayWithObjects:#"message",#"target_id",nil];
NSDictionary *params = [NSDictionary dictionaryWithObjects:obj forKeys:keys];
[[FBRequest requestWithDelegate:self] call:#"facebook.stream.publish" params:params];
}
I have also used the FBStreamDialog which works, however i'm faced with two issues there. The dialog lacks customization and i'm unable to handle the callback when the item is posted (e.g. reload the tableview)
I've been searching the internet and all of the examples are similar to the code above, so i'm not sure what i could be missing.
Thanks
You need to ask for extended permissions. After login show this:
FBPermissionDialog* dialog = [[[FBPermissionDialog alloc] init] autorelease];
dialog.delegate = self;
dialog.permission = #"status_update";
[dialog show];
Doc: http://github.com/facebook/facebook-iphone-sdk/#readme
This question discusses encrypting data on the iPhone using the crypt() function. As an alternative, is there a keychain on the iPhone and if so, what code would I use to access it in order to store login details and then retrieve them for us in an application?
One other thing to note: the keychain APIs don't work in the simulator when using older versions (2.x, 3.x) of the iPhone SDK. This could save you a lot of frustration when testing!
There is a keychain you can use - for code, the best bet is to check out the GenericKeychain sample application from Apple:
GenericKeychain sample
I really like Buzz Anderson's Keychain abstraction layer and I eagerly await Jens Alfke's MYCrypto to reach a usable state. The latter does a competent job of allowing use on Mac OS X and the iPhone using the same code, though its features only mimic a small subset of the Keychain's.
Here is what i use to store Key/Value pairs in the keychain. Make sure to add Security.framework to your project
#import <Security/Security.h>
// -------------------------------------------------------------------------
-(NSString *)getSecureValueForKey:(NSString *)key {
/*
Return a value from the keychain
*/
// Retrieve a value from the keychain
NSDictionary *result;
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecReturnAttributes, nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, key, kCFBooleanTrue, nil] autorelease];
NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];
// Check if the value was found
OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, (CFTypeRef *) &result);
[query release];
if (status != noErr) {
// Value not found
return nil;
} else {
// Value was found so return it
NSString *value = (NSString *) [result objectForKey: (NSString *) kSecAttrGeneric];
return value;
}
}
// -------------------------------------------------------------------------
-(bool)storeSecureValue:(NSString *)value forKey:(NSString *)key {
/*
Store a value in the keychain
*/
// Get the existing value for the key
NSString *existingValue = [self getSecureValueForKey:key];
// Check if a value already exists for this key
OSStatus status;
if (existingValue) {
// Value already exists, so update it
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, key, nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject:value forKey: (NSString *) kSecAttrGeneric]);
} else {
// Value does not exist, so add it
NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrGeneric, nil] autorelease];
NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, key, value, nil] autorelease];
NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
status = SecItemAdd((CFDictionaryRef) query, NULL);
}
// Check if the value was stored
if (status != noErr) {
// Value was not stored
return false;
} else {
// Value was stored
return true;
}
}
It is worth noting that these key/values will not get deleted if the user deletes your app. If a user deletes your app, then reinstalls it, the key/values will still be accessible.
Also remember that when generating an AppID, if you want more than one application to access the same Keychain information, you have to generate a wild card AppID (#####.com.prefix.*)...
With the latest version 1.2 of the GenericKeychain sample Apple provides a keychain wrapper that also runs on the iPhone Simulator. Check out at this article for details: http://dev-metal.blogspot.com/2010/08/howto-use-keychain-in-iphone-sdk-to.html
Here is one more good wrapper class from Mr.Granoff
https://github.com/granoff/Lockbox
Thanks