How to pass dynamic string into PushNotificationManager - ios

I hint error as below when i pass in data into PushNotificationManager.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectArrayI un_stringWithMaxLength:]: unrecognized selector sent to instance 0x604000018550'
Here is my code:-
[self.manager GET:#"http://api.xxxx.com/api/promotion/1" parameters:nil progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
json_promotion = responseObject;
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
NSString *strProTitle = [json_promotion valueForKey:#"title"];
NSLog(#"strProTitle - %#",strProTitle);
//Will get string "Promotion Today!" which is CORRECT
//If i put NSString *strProTitle = #"testing here", error will not appear.
[[PushNotificationManager sharedInstance]graphicsPushNotificationWithTitle:strProTitle subTitle:#"text here" body:#"desc here" identifier:#"2-1" fileName:#"Graphics.jpg" timeInterval:3 repeat:NO];
Any idea? Please help.

Your error message is basically telling you are passing an array instead of string.
I am guessing this is happening becuase valueForKey is returning an array. While parsing an object it's better to type check.
You could instead use json_promotion[0][#"title"].
If you want a better syntax I would use the following
NSString *strProTitle;
if([json_promotion isKindOfClass:[NSArray class]] {
id obj = json_promotion[0][#"title"]
if ([obj isKindOfClass: [NSString class]]) {
strProTitle = obj;
}
}

Related

Crashed if using NSMutableArray to accept json

I create a NSMutableArray and initial it in viewDidLoad
#property (nonatomic, copy) NSMutableArray *arrayDATA;
- (void)viewDidLoad {
[super viewDidLoad];
_arrayDATA = [[NSMutableArray alloc] init];
}
And I request a json by using AFNetworking from the server, the json format like this
{
"code": 0,
"statu": "success",
"datalist": [
{
"id": "1",
"name": "ADPL"
},
{
"id": "2",
"name": "GOOG"
},
{
"id": "3",
"name": "LIKE"
}
]
}
And I give the response data to arrayDATA like this
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"application/json"];
NSDictionary *params = #{#"username":username, #"password":password};
[manager POST:URL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
[self setArrayDATA:[responseObject objectForKey:#"datalist"]]; // works fine
[_arrayDATA addObject:[responseObject objectForKey:#"datalist"]]; // will crash
[self.tableview reloadData];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
As the code comment say
If I use [self setArrayDB:[responseObject objectForKey:#"datalist"]]; the function works well, but if I use [_arrayDB addObject:[responseObject objectForKey:#"datalist"]];, the function will crash, what's the correct way to use addObject here?
The crash info
[__NSSingleObjectArrayI objectForKey:]: unrecognized selector sent to instance 0x60000001a940
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectArrayI objectForKey:]: unrecognized selector sent to instance 0x60000001a940'
I suppose there is an error and arrayDATA and arrayDB are the same.
But the crash is because you are setting the element "datalist" of the responseObject to arrayDB. Then arrayDB is a NSArray, not an NSMutableArray. So you cannot add more elements.
On the other hand, you don't need to init the mutable array in viewDidLoad if latter you are going to set a new pointer to a new object.
Try to change the setArrayDB: line with this:
self.arrayDB = [NSMutableArray arrayWithArray:[responseObject objectForKey:#"datalist"]];
First of all return type of [responseObject objectForKey:#"datalist"] is Array and not NSDictionary.
Point 1
[self setArrayDATA:[responseObject objectForKey:#"datalist"]]; // works fine
This is fine because you are setting array for an array.
Point 2
This will crash because you are adding array as addObject.
[_arrayDATA addObject:[responseObject objectForKey:#"datalist"]];
You should use as below to make it working
[_arrayDATA addObjectsFromArray:[responseObject objectForKey:#"datalist"]];
^^^^^^^^^^^^^^^^^^^

Terminating app due to uncaught > exception 'NSInvalidArgumentException'

This seems like it should be pretty straight forward - but alas, I'm getting a crash. I'm simply trying to set my UILabel with the text returned from the users_name field:
.m
NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:#"u000" forKey:#"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.userData = [responseObject mutableCopy];
self.username.text = [self.userData objectForKey:#"users_name"];
dispatch_async(dispatch_get_main_queue(), ^(void){
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
The console data returns:
2016-04-05 12:25:36.877 [1331:350069] This is the Other User Data (
{
address = "Vancouver";
userbio = "There is currently no bio available for this user. If you have added your bio, and require assistance, please contact the Team.";
"users_name" = Brittany;
},
That said, this line is causing the crash:
self.username.text = [self.userData objectForKey:#"users_name"];
And this is the error:
2016-04-05 12:25:36.878 [1331:350069] -[__NSCFArray objectForKey:]:
unrecognized selector sent to instance 0x15a23c100 2016-04-05
12:25:36.881 [1331:350069] * Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[__NSCFArray
objectForKey:]: unrecognized selector sent to instance 0x15a23c100'
* First throw call stack: (0x181d51900 0x1813bff80 0x181d5861c 0x181d555b8 0x181c5968c 0x1000cce9c 0x1000c72bc 0x1000d3cc4
0x100459bf0 0x100459bb0 0x10045f658 0x181d08bb0 0x181d06a18
0x181c35680 0x183144088 0x186aacd90 0x1000d4c88 0x1817d68b8)
libc++abi.dylib: terminating with uncaught exception of type
NSException
How might I fix this? It seems like it should be simple...
I suppose userData is an Array type. Array have no key values.
Try: [[self.userData objectAtIndex:0] objectForKey:#"users_name"];

Error : unrecognized selector sent to instance

I have been through similar questions, but not able to solve my issue.
The issue is i have a call to API and i am storing the response in a NSDictionary, the response is a single value like RED or GREEN:
saveBlock:^( NSDictionary *data, NSError **err )
{
if (! *err)
{
if (data)
{
NSLog(#"KEY %# - VALUE %#",data.allKeys,data.allValues); //Error because i am performing .allKeys on type NSString
NSString *str = data; // error because i am assigning NSDictionary to string.
}
}
else
{
NSLog(#" error is : - %#",*err);
}
}];
Aren't these two error messages contradicting each other ? Anyone explanation about this issue. Thank you.
EDIT The first NSLog gives this error : *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString allKeys]: unrecognized selector sent to instance 0x170664b80'
(This error appears only at runtime and not when i type data.allKeys)
And the second NSLog gives this: Incompatible pointer type, initialising NSString* with an expression of type NSDictionary *
(This is shown after typing, i don't know what this type of error is called :D)
It is a standard practice to check your response type and error message before performing any operation, sort of defensive coding.
eg.
DLog(#"Object:%#,Error:%#",responseObject,error);
if (error != nil) {
DLog(#"Got error from API:%#",error);
return ;
}
if (!responseObject) {
DLog(#"Response object is not valid, returning...");
return;
}
if (![responseObject isKindOfClass:[NSDictionary class]]) {
DLog(#"Incorrect type of returned object, expecting NSDictionary, got:%#",[responseObject class]);
return;
}
Also I am pretty sure you are getting a NSString cause you don't get an error when assigning a NSDictionary to a NSString
Webservice response data 'data' should be NSDictionary, but in your case you are getting NSString. For NSString class, there is no allKeys method available, that is why you are getting crash. One thing is to validate for NSDictionary like.
if (data && [data isKindOfClass:[NSDictionary class]]) {
NSLog(#"KEY %# - VALUE %#",data.allKeys,data.allValues); //Error because i am performing .allKeys on type NSString
NSString *str = data; // error because i am assigning NSDictionary to string
}
Or remove NSLog

Multi NSDictionary returns string instead of child

I am trying to access keys from a multi NSDictionary.
This is my output from NSLog
Berlijn[23667:60b] data = {
1 = {
data = (
4,
0,
0,
0
);
key = "June 2014";
};
}
When I try to loop through this dictionary and log the key I get NSInvalidArgumentException because key is a NSString.
This is my current code:
- (void) updateRating: (int) companyID {
APICaller *api = [[APICaller alloc] init];
[api setUrl:#"http://domain.examle/api/getcompanyhistory.php"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *parameters = #{
#"token": [[[FBSession activeSession] accessTokenData] accessToken],
#"device_token" : [defaults stringForKey:#"uniqueToken"],
#"companyid" : #(companyID)
};
[api setParameters: parameters];
[api sendPostRequest: ^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"data = %#", responseObject);
for(NSDictionary *contentData in responseObject) {
NSLog(#"contentData = %#", [contentData objectForKey:#"key"]);
}
[self.tableView reloadData];
}: ^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
As NSDictionary is a dictionary I don't know why it returns a string.
Update (error message):
2014-06-02 01:41:41.386 Berlijn[23747:60b] -[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x1784253e0
2014-06-02 01:41:41.387 Berlijn[23747:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x1784253e0'
*** First throw call stack:
(0x1860a309c 0x192021d78 0x1860a7d14 0x1860a5a7c 0x185fc54ac 0x1000eb8ac 0x1000ea014 0x1925f0420 0x1925f03e0 0x1925f356c 0x186062d64 0x1860610a4 0x185fa1b38 0x18b9c7830 0x188fe00e8 0x1000eaff4 0x19260baa0)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Just because you call contentData a dictionary does NOT make it one.
Fast enumeration of a dictionary iterates over keys, NOT values. Your key is a string (even though you call it an NSDictionary) and will throw an exception when you try to call objectForKey: on it.
Since responseObject is a dictionary you can iterate over the keys AND values using enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop)).
Another option is to use fast enumeration correctly like so...
for(NSString *key in responseObject) {
NSLog(#"contentData = %#", [responseObject objectForKey:key]);
}

Getting Terminating app due to uncaught exception 'NSInvalidArgumentException' accessing a web api

I am trying to consume a simple web api that returns the data below in Objective C using AFJSONRequestOperation.
Results; (
{
Category = Groceries;
Id = 1;
Name = "Tomato Soup";
Price = 1;
},
{
Category = Toys;
Id = 2;
Name = "Yo-yo";
Price = "3.75";
},
{
Category = Hardware;
Id = 3;
Name = Hammer;
Price = "16.99";
}
)
My Objective-C call looks like this:
//not the real URL, just put in to show the variable being set
NSURL *url = [NSURL URLWithString:#"http://someapi"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Results; %#", JSON);
self.resultsArray= [JSON objectForKey:#"Results"];
}
failure: ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error ,id JSON) {
//http status code
NSLog(#"Received Error: %d", response.statusCode);
NSLog(#"Error is: %#", error);
}
];
//run service
[operation start];
When I run my code, I can see the data returned in the NSLog statement. However I get the following error when I try to set the results to my array using the JSON objectForKey statement.
-[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0xe466510
2013-09-30 20:49:03.893 ITPMessageViewer[97459:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0xe466510'
I'm fairly new to Objective-C, and can't figure out why this isn't working. Any help or ideas would be appreciated.
The result you are getting is an Array
objectForKey: is a NSDictionary method
So use valueForKey: which is a NSArray method.
self.resultsArray= [JSON valueForKey:#"Results"];
In your code, the JSON ( result ) need to follow this method to use :
self.resultsArray = (NSArray *)JSON;
It'll force the " id " type to NSArray for your self.resultsArray type ( It is an NSArray, right ? ), then you can use this method to enumerate it.
[self.resultsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSDictionary *_eachResult = (NSDictionary *)obj;
[_eachResult objectForKey:#"Category"];
//...
}];
Hope it can help you.
I managed to update my web service to return data in a format that the AFJSONRequestOperation was happy with. This allowed me to get the JSON to parse properly. Still not sure why it needed this dictionary combo, but glad it worked.
In case anyone is writing a web api in C# to talk to objective C, this is what I did:
The update was to return the following object as JSON (code is in C#).
Dictionary > with string = "results" and the IEnumerable is my strongly typed array of objects.
public Dictionary<string, IEnumerable<Product>> GetAllProducts()
{
var sortedProuct = results.OrderBy(a => a.Category);
var proddict = new Dictionary<string, IEnumerable<Product>>()
{
{ "results", results},
};
return proddict;
}
this translates to:
Results; {
results = ({
Category = Groceries;
Id = 1;
Name = "Tomato Soup";
Price = 1;},
....

Resources