NSInvalidArgumentException NSDictionary count - iphone

i have write a NSDictionary Category. The Category has a method calls "initWithJSONURL".
Here the code:
- (id)initWithJSONURL:(NSURL *)url
{
self = [super init];
if (self) {
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:url
options:NSUTF8StringEncoding
error:&error];
if (!data) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"connection failed"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:#"cancel"
otherButtonTitles:nil];
[alert show];
} else {
self = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"invalid data"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:#"cancel"
otherButtonTitles:nil];
[alert show];
}
}
}
return self;
}
And here the code from my ViewController viewDidLoad
NSURL *url = [NSURL URLWithString:#"http://localhost:8888/json.php"];
NSDictionary *dict = [[NSDictionary alloc] initWithJSONURL:url];
NSLog(#"%#", dict);
If I use an correct URL everything works perfect.
But if the URL not correct, the App crash.
I don't know why, it should not crash, it should show the alert View.
The consoles show:
erminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSDictionary count]: method sent to an uninitialized immutable dictionary object'
I hope anybody can help me and sorry for my bad english.

You want to call [self init] instead of [super init]. A category is not a subclass, so [super init] means [NSObject init]. The designated initializer of NSDictionary is never called and the internal dictionary structures are staying unitiliazed.

Related

SWIFT: CDA to iOS 10 Health app

Is there any way to send a xml file (CDA) to health app from another application? Because my application is getting a xml file from a source and I want to send it directly to the new health app (iOS 10).
Create an HKCDADocumentSample and save it with an HKHealthStore.
First, check for authorization
(void) checkForAuthorization {
if ([HKHealthStore isHealthDataAvailable]) {
NSSet *setRead = [NSSet setWithObjects [HKObjectTypedocumentTypeForIdentifier:HKDocumentTypeIdentifierCDA], nil];
NSSet *setWrite = [NSSet setWithObjects:[HKObjectType documentTypeForIdentifier:HKDocumentTypeIdentifierCDA], nil];
[_store requestAuthorizationToShareTypes:setWrite readTypes:nil completion:^(BOOL success, NSError * _Nullable error) {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
} else if (success) {
[self performSelectorOnMainThread:#selector(addDocumentToHealthApp) withObject:nil waitUntilDone:NO];
}
NSLog(#" Success = %#",success? #"YES" : #"NO");
} ];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Health Kit not supported in device." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
Second, add Record wmthod this will add a Health record to health app.
(void) addRecordToHealthApp
{
NSURL *cdaPath = [[NSBundle mainBundle] URLForResource:#"sample" withExtension:#"xml"];
NSString*stringPath = [cdaPath absoluteString];
NSData *dataOfCDAFile = [NSData dataWithContentsOfURL:[NSURL URLWithString:stringPath]];
NSDate *now = [NSDate date];
int daysToAdd = 7;
NSDate *newDate1 = [now dateByAddingTimeInterval:60*60*24*daysToAdd];
NSError *err;
HKCDADocumentSample *doc = [HKCDADocumentSample CDADocumentSampleWithData:dataOfCDAFile startDate:[NSDate date] endDate:newDate1 metadata:nil validationError:&err ];
UIAlertView *alert;
if (err) {
alert = [[UIAlertView alloc] initWithTitle:#"Error" message:err.localizedDescription delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
[_store saveObject:doc withCompletion:^(BOOL success, NSError * _Nullable error) {
NSLog("Stored %#",success?#"YES":#"NO");
}];
}

UIAlertView on main queue crashing.

I have an issue showing a UIAlertView on the main thread. I'm not sure why but it keeps crashing, despite me running on the main thread. The following block is on the background thread, but I have the alert on the main as below:
void (^removeFromCalendar)(NSString *, NSString *, EKEventStore *) = ^(NSString *error, NSString *eventKey, EKEventStore *eventDB) {
EKEvent *myEvent = [eventDB eventWithIdentifier:eventKey];
NSError *err = noErr;
if(myEvent != NULL && myEvent != (id)[NSNull null]) {
[eventDB removeEvent:myEvent span:EKSpanThisEvent error:&err];
} else {
// Event was not found, nothing to do
return;
}
[eventDB release];
if (!err || err == noErr) {
NSLog(#"Deleted event %#", myEvent.title);
// Show alert on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
// Showing the alert for unattending
NSString *resultString = #"This event was removed from your calendar.";
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Info" message:resultString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil] autorelease];
[alert show];
});
return;
}
error = err.description;
};
If I comment out the bottom where it shows the alert, everything is fine. But for the alert, I keep getting a EXC_BAD_ACCESS error. Can somebody explain why? It's on the correct thread, and I cant for the life of me understand where the memory issue could come from!
May be you view is being released when you finish until you finish with the background queue. So, for safety why dont you use it like this;
...........
UIViewController __weak *myController = self;
dispathch_async(backgroundQueue, ^{
UIViewController __strong *myStrongController = myController;
...............
dispatch_async(dispatch_get_main_queue(), ^{
if(myStrongController){
// Showing the alert for unattending
NSString *resultString = #"This event was removed from your calendar.";
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Info" message:resultString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil] autorelease];
[alert show];
}
});
}).
This is how you present an alert view:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"<#(NSString *)#>" message:#"<#(NSString *)#>" delegate:self cancelButtonTitle:#"<#(NSString *)#>" otherButtonTitles:nil];
[alert show];
[alert release];
Instead of using dispatch_async, why not use the objective C call:
[self performSelectorOnMainThread
You might have to package it up in its own method. Alternatively, call it using:
[self performSelector:#selector(myAlertMethod) withObject:nil afterDelay:0.25]
These methods have been tried and true since day 1.

request send get error: [CFString release]: message sent to deallocated instance 0x6a83e00

I want to check the app version from apple so I send request like below
- (void)connectToCheckVersion{
NSString *url = #"http://itunes.apple.com/lookup?id=466424846";
TTURLRequest *_request = [TTURLRequest requestWithURL:url delegate:self];
_request.httpMethod = #"GET";
_request.cachePolicy = TTURLRequestCachePolicyNone;
_request.shouldHandleCookies = NO;
TTURLJSONResponse* response = [[TTURLJSONResponse alloc] init];
_request.response = response;
TT_RELEASE_SAFELY(response);
[_request send];
}
- (void)requestDidFinishLoad:(TTURLRequest*)request {
TTURLJSONResponse* response = request.response;
NSDictionary* json = response.rootObject;
NSArray *results = [json objectForKey:#"results"];
NSString *version;
for (NSDictionary *rawResult in results) {
version = [rawResult objectForKey:#"version"];
}
NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
if (version != nil && currentVersion != nil && ![version isEqualToString:currentVersion]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"info"
message:#"newer version"
delegate:self
cancelButtonTitle:#"ok"
otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
and after [_request send]; will get [CFString release]: message sent to deallocated instance 0x6a83e00. I checked all Strings in this method seems they are ok, and I can still get correct response from remote.
If I comment out this connectToCheckVersion method then no any problem.
Any diea?
I think that you should retain the _request variable and save it as a member.
Because it will autorelease after the function is returned.
You have to release it after the request is successed or failed.
Thank you.

How to upload photos to Plixi (Tweetphoto) using Oauth?

I am creating an iphone application in which I have to upload photos using different services.
I am successful in uploading photos with Twitpic & YFrog but not able to do with Plixi.
I am using Oauth ,as Twitter is not allowing Basic authentication.
If anyone has tried with Plixi ,please help me out!!
I have googled a lot but not getting any relevant documentation for the new Oauth for Plixi.
Finally, I am with a solution for my problem :)
If anyone is also stuck with this problem, just add the TweetPhoto folder from the following application link:
http://code.google.com/p/tweetphoto-api-objective-c/downloads/detail?name=TPAPI-Objective-C-Library.zip
Change the tweetphoto urls for plixi now.
Also, can refer to my following code for making function calls:
-(void)uploadtoTweetPhoto{
NSString *message = [self.tweetTextView.text stringByReplacingOccurrencesOfString:#"Max. 140 characters" withString:#""];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
if((message == nil) || ([message isEqual:#""])){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Please enter your tweet message.." message: #"" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
[alert show];
[alert release];
}
else{
[dictionary setObject:message forKey:#"message"];
}
if([dictionary count] == 1){
[indicator startAnimating];
[NSThread detachNewThreadSelector:#selector(uploadPhotoToTweetPhoto:) toTarget:self withObject:dictionary];
}
[dictionary release];
}
- (void)uploadPhotoToTweetPhoto:(NSDictionary *)dictionary{
NSString *message = [dictionary objectForKey:#"message"];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *accessTokenKey = [[NSUserDefaults standardUserDefaults] valueForKey:#"oauth_token"];
NSString *accessTokenSecret = [[NSUserDefaults standardUserDefaults] valueForKey:#"oauth_token_secret"];
TweetPhoto *tweetPhoto = [[TweetPhoto alloc] initWithSetup:accessTokenKey identitySecret:accessTokenSecret apiKey:Plixi_API_Key serviceName:#"Twitter" isoAuth:YES];
NSData *dat =[tweetPhoto upload:UIImageJPEGRepresentation(self.imgView.image,0.8) comment:message tags:#"" latitude:23.4646 longitude:-87.7809 returnType:TweetPhotoCommentReturnTypeXML];
NSString *status =[NSString stringWithFormat:#"%i",[tweetPhoto statusCode]];
[tweetPhoto release];
[self performSelectorOnMainThread:#selector(photoUploadedtoTweetPhoto:) withObject:status waitUntilDone:[NSThread isMainThread]];
[pool release];
}
- (void)photoUploadedtoTweetPhoto:(NSString*)status{
[indicator stopAnimating];
if([status isEqualToString:#"201"])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Tweet Posted" message: #"" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
[alert show];
[alert release];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Tweet Failed" message: #"" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
I'm curious as to the phrase you used in Google. In any case, googling "plixi api" tool me to this page, which links to a Cocoa wrapper on Google Code.

Regarding xml parsing in iphone

I am developing an application in which I am doing XML parsing. I found an error in the [xmlparse parse] method.
Error:
[NSCFString bytes]: unrecognized selector sent to instance 0x3df6310
2010-04-30 00:09:46.302 SPCiphone2[4234:1003] void SendDelegateMessage
(NSInvocation*): delegate (<CFNotificationCenter 0x3d09670 [0x87dca0]>)
failed to return after waiting 10 seconds. main run loop mode:
kCFRunLoopDefaultMode
Code snippet:
responseOfWebResultData = [[NSMutableString alloc]
initWithData:responseData
encoding:NSUTF8StringEncoding];
NSLog(#"result: %#", responseOfWebResultData);
// starting the XML parsing
if (responseOfWebResultData) {
#try {
xmlParser = [[NSXMLParser alloc] initWithData:responseOfWebResultData];
[xmlParser setDelegate:self];
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
[responseOfWebResultData release];
}
#catch (NSException *e) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Please"
message:[e reason]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
You should not be passing in a NSString* into initWithData:. You should do this:
xmlParser = [[NSXMLParser alloc] initWithData:responseData];
The error says that you're sending the message bytes to an instance of NSCFString, which is a NSString*, even though you declared it as a NSMutableString*, because this is a dynamically typed language but the class types are not automatically converted if you try to cast it to something else.