This process is sending eMails, and it works fine, but the framework wants the body of the email to be an NSArray. So I try to convert the NSString to a NSDictionary to include with the NSArray here:
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:kSKPSMTPPartContentTypeKey,
message,kSKPSMTPPartMessageKey,kSKPSMTPPartContentTransferEncodingKey, nil];
then I implement that here:
smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];
Overall, here is my code:
NSLog(#"Start eMail");
SKPSMTPMessage *smtpTestMessage = [[SKPSMTPMessage alloc] init];
smtpTestMessage.fromEmail = #"***#gmail.com";
smtpTestMessage.toEmail = #"***#yahoo.com";
smtpTestMessage.relayHost = #"smtp.gmail.com";
smtpTestMessage.requiresAuth = YES;
smtpTestMessage.login = #"***#gmail.com";
smtpTestMessage.pass = #"***";
smtpTestMessage.subject = #"***";
smtpTestMessage.wantsSecure = YES;
smtpTestMessage.delegate = self;
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:kSKPSMTPPartContentTypeKey,
message,kSKPSMTPPartMessageKey,kSKPSMTPPartContentTransferEncodingKey, nil];
smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];
[NSString stringWithFormat:#"%#",message];
[smtpTestMessage send];
NSLog(#"sent");
But sadly enough, when I run the app, the eMail gets to the last stage... Then the app terminates saying
2013-10-15 00:43:50.512 BullyBox[3662:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(0x2f61ae8b 0x399156c7 0x2f5540cb 0x2f556749 0xc77f3 0x31dd555f 0x31dd54fb 0x31dd54cb 0x31dc10f3 0x31dd4f13 0x31dd4bdd 0x31dcfc09 0x31da4f59 0x31da3747 0x2f5e5f27 0x2f5e53ef 0x2f5e3bdf 0x2f54e541 0x2f54e323 0x342852eb 0x31e051e5 0xc91b5 0x39e0eab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
EDIT
Now I keep getting the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString appendString:]: nil argument'
Any help is greatly appreciated! Thank you for even reading this! xD <3
Make sure plainPart is created successfully and not a nil.
It's tough to judge but if I had to guess plainPart is not getting created. Why do I think this? Let's take a look at the error:
[__NSPlaceholderArray initWithObjects:count:]:
This points to an alloc/init sequence of calls. The only place in the code you shared where you are allocating an array is here:
smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];
Therefore, if you are trying to create an array with a nil object, plainPart, then it makes sense why you are getting an error about trying to insert a nil object at location 0.
Try setting a breakpoint right at this call in your code. This will help you narrow down where the crash happens.
I am not sure what you are trying to do here
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:kSKPSMTPPartContentTypeKey,
message,kSKPSMTPPartMessageKey,kSKPSMTPPartContentTransferEncodingKey, nil];
but based on you naming convention you are storing a key in a value location. Also you could switch to the modern objective-C syntax
NSDictionary *plainPart = #{
message: kSKPSMTPPartContentTypeKey,
kSKPSMTPPartContentTransferEncodingKey: kSKPSMTPPartMessageKey
};
This is equivalent to what you wrote, but more readable. As stated in the other answers it look like there is a problem with the creation of plainPart. Hopefully looking at this should make it easier to debug.
Check first this line smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];.
Whether it is smtpTestMessageallocated if yes then check any data exist inside this or not
Related
This question already has answers here:
App Crashing: Mutating method sent to immutable object
(4 answers)
Closed 7 years ago.
I want to add an object to an existing NSMutableArray which already has data in it.
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *json = [Server getMsgRecordwithfid:self.fid];
self.msgRecords = [[NSMutableArray alloc] init];
self.msgRecords = [json objectForKey:#"msg_record"];
}
- (IBAction)sendBtn:(id)sender {
NSDictionary *json = [Server insertNewMsg:data];
[self.msgRecords addObject:json];
}
When I run the above code, the program crashes at [self.msgRecords addObject:json];. And then it gives the below error message.
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
What's wrong with my code?
What's wrong of my code?
Your code is writing over the NSMutableArray, replacing a mutable collection with an immutable one that you retrieve from json.
To fix this, call mutableCopy on the array that you retrieve:
// The first line is no longer necessary
//self.msgRecords = [[NSMutableArray alloc] init];
self.msgRecords = [[json objectForKey:#"msg_record"] mutableCopy];
I have another question about checking the existence of valueForKey.
Here's my code:
id _jsonId = [NSJSONSerialization JSONObjectWithData:[_json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&_error];
Monday = [[NSMutableArray alloc] init];
if ([_jsonId valueForKey:#"Mon"]!= Nil) {
_keyMon = [_jsonId valueForKey:#"Mon"];
[Monday addObject:#"Monday"];
for (int i=0; i<5; i++) {
if ([_keyMon objectAtIndex:i]!=[NSNull null]) {
[Monday addObject:[_keyMon objectAtIndex:i]];
}
}
} else {
[_keyTues addObject:#"No Class For Today"];
[Monday addObject:[_keyMon objectAtIndex:1]];
}
The idea is, if the _jsonId valueForKey came back nothing, I can add this NSStringaddObject:#"No Class For Today incase XCode tells me that:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
like it has been telling me now. Anyone have any solution?
I tried if ([_jsonId valueForKey:#"Mon"]!= Nil) didn't work.
I tried if ([_jsonId valueForKey:#"Mon"]!= nil) didn't work.
I tried if ([_jsonId valueForKey:#"Mon"]!= (id)[NSNull null]) didn't work.
I tried if ([_jsonId valueForKey:#"Mon"]!= [NSNull null) didn't work.
I know that _jsonId valueForKey is came back as a pointer, but I have no idea how to check if the pointer is null(or nil in Objective-C if I'm correct). Please help me.
UPDATE:
I have tried using objectForKey and here is a code(_jsonId objectForKey is nil, that I know to try testing the code)
if (_jsonId[#"Sun"]== nil) {
[_keySun addObject:#"No Class For Today"];
[Monday addObject:[_keySun objectAtIndex:1]];
}
else{
_keySun = [_jsonId objectForKey:#"Sun"];
[Monday addObject:#"Sunday"];
for (int i=0; i<5; i++) {
if ([_keySun objectAtIndex:i]!=nil) {
[Monday addObject:[_keySun objectAtIndex:i]];
}
}
}
Still, XCode telling me that I'm add a nil into NSArray.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
This is driving me crazy...
_jsonId as defined by:
id _jsonId = [NSJSONSerialization JSONObjectWithData:[_json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&_error];
... will be either an array or a dictionary. Based on your code I think you're assuming that it's always a dictionary. So you probably want to add:
if (![_jsonId isKindOfClass:[NSDictionary class]]) ...
You then want to know what's in a dictionary, if anything. So use objectForKey:. Or, better, just _jsonId[#"Mon"]. You'll get an object or you'll get nil.
valueForKey: is a completely different mechanism, key-value coding. It is defined on NSObject so inherited by NSDictionary as well as just about everything else. It is defined to raise an exception for an unknown key. Since it raises an exception instead of returning a result, your attempts to compare a result are ineffective.
I think I figured it out. Let's look at the code:
if (_jsonId[#"Sun"]== nil) {
[_keySun addObject:#"No Class For Today"];
[Monday addObject:[_keySun objectAtIndex:1]];
}
else {
_keySun = [_jsonId objectForKey:#"Sun"];
...
If there is an object for the key "Sun" then you store it into _keySun. If there is no object, then you store nothing into _keySun. _keySun will be nil. You send an addObject message to _keySun - but any message sent to a nil object does nothing. You then call [_keySun objectAtIndex:1]. Again, sending a message to a nil object does nothing, and returns nil, which is why you add nil to the Monday object and get a crash.
If you had set _keySun to an empty NSMutableArray, you would have crashed for another reason: You try to add one object. You can read that one object with objectAtIndex:0. But to read objectAtIndex:1 you need two objects in the array.
BTW. You will get [NSNull null] from the JSON parser if the JSON document that you are reading contains an explicit null. So if your JSON contains "Sun": null then objectForKey:#"Sun" will give [NSNull null]. If your JSON doesn't contain the key "Sun" at all, objectForKey:#"Sun" will give nil.
I basically get this error
'NSInvalidArgumentException', reason: '-[__NSCFConstantString objectForKey:]: unrecognized selector sent to instance 0x581f0'
on my program. I think it refers to this call I make,
if (data != nil) {
if([data objectForKey:#"username"]){
// NSArray *check= [[NSArray alloc]init];
//check=[data allValues];
[dict setObject:[data allValues] forKey:#"args"];
}else{
[dict setObject:[NSArray arrayWithObject:data] forKey:#"args"];
}
at the setObject:[data allValues]. I don't know why it gives that error but data is an NSDictionary and I'm getting all the values and placing it in an array.
Is the error happening here:
if([data objectForKey:#"username"]){
I assume so, as that is the only place objectForKey seems to be called. You are calling it on a variable called 'data', which i'm guessing simply is not a dictionary. You should NSLog its type to see.
I have a NSDictionary with some parameters I want to display in a UITextField. but
firstname.text = [userdata objectForKey:#"firstname"];
throws an exeption. If I use NSLog on [userdata objectForKey:#"firstname"]; it shows the right value.
This is the thrown exception:
2012-07-05 15:55:56.533 Project[13642:f803] -[__NSArrayM
_isNaturallyRTL]: unrecognized selector sent to instance 0x68c4e20 2012-07-05 15:55:56.534 Project[13642:f803] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM
_isNaturallyRTL]: unrecognized selector sent to instance 0x68c4e20'
If I use
firstname.text = [NSString stringWithFormat:#"%#",[userdata objectForKey:#"firstname"]];
it works, but it puts the values in brackets.
What seems to be the problem here? And why doesn't the first attempt work?
_isNaturallyRTL
is an undocumented NSString method. It seems that
[userdata objectForKey:#"firstname"]
is an NSMutableArray (guessed from class name), which you're trying to use as a string. When you use a format string with the %# format specifier, it calls the -description method of the object to be formatted/printed (so does NSLog), and the description of an NSArray is an NSString that looks like
[ "description of first element", "description of second element" ]
etc., that's why it puts your text in brackets but doesn't crash.
All in all, use
[[userdata objectForKey:#"firstname"] objectAtIndex:0]
instead.
firstname.text = [[userdata objectForKey:#"firstname"]stringValue];
Does this do any difference?
It would appear that [userdata objectForKey:#"firstname"] is returning an array that contains just the string you are after. Take a look at where you set the value for "firstname" and change it to be just the string that you are after.
I'm getting an exception after attempting to remove an object from a NSMutableDictionary. The relevant code follows. The 'settings' is passed to the method and can be a NSDictionary or a NSMutableDictionary.
NSMutableDictionary *mutableSettings = nil;
if ([settings isKindOfClass:[NSMutableDictionary class]])
mutableSettings = (NSMutableDictionary *)settings;
else
mutableSettings = [[[NSMutableDictionary alloc] initWithDictionary:settings] autorelease];
[mutableSettings removeObjectForKey:#"akey"];
This crashes with
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object'
Whats wrong with this? Thanks.
The problem here is that both NSDictionary and NSMutableDictionary return __NSCFDictionary as their class, due to the fact that NSDictionary is a class cluster.
I think you will just have to make a mutable copy of the settings dictionary whether it is mutable or not.
NSMutableDictionary *mutableSettings = [settings mutableCopy];