My iOS app crashes every time a user hits 'next' when one of the fields (they're strings) is empty. How do I make it to where this doesn't happen?
emailBody = [emailBody stringByAppendingString:nameField.text];
Here's one of the lines that is causing the crash; it's trying to pull the data from nameField.text, but in some cases it's empty and this crashes it.
You shouldn't assign a default value - instead you should secure your code so it does not crash.
In this case, you could do the following:
if (nameField.text) {
emailBody = [emailBody stringByAppendingString:nameField.text];
}
Related
Let me start by saying I'm not proficient in objective c, nor am I an iOS developer. I'm working on a react-native app and find that I'm having to dig into the native code. So, I appreciate your patience with me and would also very much appreciate if you made zero assumptions about what I might, or might not know. Thx!
I'm trying to use react-native-mail but it fails to attach the photo I've selected to the email.
In troubleshooting, I jumped into Xcode's debugger for the first time. Stepping through the code, it appears as though the attachmentPath which is something like file:///var/mobile/... is being assigned to the variable fileData as type NSData. But then, taking one step further into the code it becomes nil.
I'm not sure why this would happen nor how to go about troubleshooting this. Here's an image of the debugger session with 3 screenshots stitched together side-by-side.
Here's the code: RNMail.m
All pointers, tips, guidance, and advice welcome
In your first screenshot, the debugger is still on the line that declares and assigns the fileData variable. This means that that line hasn't actually been executed yet. -dataWithContentsOfFile: hasn't yet been called, and thus the value that appears to be in fileData is not meaningful; what you're seeing is just garbage data prior to the variable actually being assigned. In your second screenshot, the -dataWithContentsOfFile: method has finished running, and it has returned nil. What you need to do is to figure out why you're getting nil from -dataWithContentsOfFile:. Perhaps the path to the file is incorrect, or perhaps you don't have permission to read it, or perhaps you have a sandboxing issue.
I would suggest using -dataWithContentsOfURL:options:error: instead of -dataWithContentsOfFile:. This will return an error by reference (create an NSError variable ahead of time, assign it to nil, pass a pointer to the error as the third parameter to -dataWithContentsOfURL:options:error:, and then check the error if the method returns nil). More likely than not, the contents of the error will explain what went wrong when trying to read the file.
EDIT: Looking at your screenshot again, the problem is clear; from the description of the contents of attachmentPath, we can see that it isn't a path at all, but instead it contains a URL string (with scheme file:). So you cannot pass it to the APIs that use paths. This is okay, since the URL-based mechanisms are what Apple recommends using anyway. So, just turn it into a URL by passing the string to -[NSURL URLWithString:] (or, even better, -[[NSURLComponents componentsWithString:] URL], since it conforms to a newer RFC). So, something like:
// Get the URL string, which is *not* a path
NSString *attachmentURLString = [RCTConvert NSString:options[#"attachment"][#"path"]];
// Create a URL from the string
NSURL *attachmentURL = [[NSURLComponents componentsWithString:attachmentURLString] URL];
...
// Initialize a nil NSError
NSError *error = nil;
// Pass a pointer to the error
NSData *fileData = [NSData dataWithContentsOfURL:attachmentURL options:0 error:&error];
if (fileData == nil) {
// 'error' should now contain a non-nil value.
// Use this information to handle the error somehow
}
I am new in iOS so please help me. I am getting some messages from server with a key "messageId". I am showing those messages in tableview. Now I have to differentiate that if there is new message which is being open first time in that tableview, I have to change the colour of that message in the cell.
cell.notificationMessageDate.text = [[self.notifications objectAtIndex:indexPath.row] valueForKey:#"msgCreatedDate"];
cell.notificationMessageText.text = [self stringByStrippingHTML:[[self.notifications objectAtIndex:indexPath.row] valueForKey:#"message"]];
NSString *str = [[self.notifications objectAtIndex:indexPath.row] valueForKey:#"messageId"];
self.isAlreadyExist = false;
if (str ) {
cell.backgroundColor = [UIColor whiteColor];
} else {
}
#AADi i see that you are getting message from notifications. I dont know what structure you have implemented.
To implement what you want, what i feel is you must implement a dictionary or array where you store your data from wherever you are fetching it. Then pass the count of the array or dict. to table. Now maintain a variable which stores the previous count of the array or dict. In cell for row, compare the index path with the previous count of the array or dict. If the index path is greater then previous count simply change the background for the cell at that index path and update the value of previous count with current count.
If you don't understand or have any doubts then ask here.
Hope it will help you.
A word of advice, its not a good approach to check if message is new locally. If a user uninstalls the app and reinstall it then all the messages would appear new to the user even thought she may have read them.
A better approach is to send boolean variable, something like seen or read, along with other details of message from the server and display the cells accordingly. To mark a message as read or seen you can make an API call to the server with the messageID reflecting it in the backend.
In my iOS app I have following code:
case SASpeechSubCase03:
{
SAActivity currentActivity = self.mediator.selectedActivity;
NSString *sActivity = NSLocalizedString(#"activity", #"activity");
NSString *sActivity2 = NSLocalizedString(#"another activity", #"another activity");
if(currentActivity == SAActivityWalk)
{
sActivity = NSLocalizedString(#"walk", #"walk");
sActivity2 = NSLocalizedString(#"walking", #"walking");
}
else
{
sActivity = NSLocalizedString(#"run", #"run");
sActivity2 = NSLocalizedString(#"jogging", #"jogging");
}
return [NSString stringWithFormat:speech.text, sActivity, sActivity2];
break;
}
When I run bots on it, it gave me following warning:
Bot Issue: analyzerWarning. Dead store.
Issue: Value stored to 'sActivity' during its initialization is never read.
File: SAAnnouncementService.m.
Integration Number: 42.
Description: Value stored to 'sActivity' during its initialization is never read.
Bot Issue: analyzerWarning. Dead store.
Issue: Value stored to 'sActivity2' during its initialization is never read.
File: SAAnnouncementService.m.
Integration Number: 42.
Description: Value stored to 'sActivity2' during its initialization is never read.
Can someone tell what the problem might be here?
Any kind of help is highly appreciated!
The problem is that you initialized the variables and then directly started the if-else blocks, without using, i.e. reading, the initial values.
When execution gets to the if-else blocks, it will definitely be assigned a new value, no matter what value it was before.
With the following line :
NSString *sActivity = NSLocalizedString(#"activity", #"activity");
NSString *sActivity2 = NSLocalizedString(#"another activity", #"another activity");
You are assigning string values to the sActivity and sActivity2 objects.
Then, these two values are modified in either if or else statement.
But, as the static analyzer mentions, the initial values of these objects (#"activity" and #"another activity") were never read before the second assignment (in if / else statement).
To avoid this warning you can replace the two lines above, by :
NSString *sActivity = nil;
NSString *sActivity2 = nil;
Hope that helps ;)
When you get a warning, the compiler tells you "what you are doing here looks like nonsense, and is most likely not what you want".
Look at these two statements:
NSString *sActivity = NSLocalizedString(#"activity", #"activity");
NSString *sActivity2 = NSLocalizedString(#"another activity", #"another activity");
Does the assignment serve any purpose? It doesn't look like it. So the compiler thinks "either the guy made a rather expensive call that is completely pointless, or he actually intended to use the result of NSLocalizedString but stored it in the wrong place. "
Since the compiler assumes that people don't do pointless things, it assumes that there is a bug in your code and tells you about it. It's the kind of thing where a human reviewing your code would stop and ask you what you were intending to do there.
In your codes, sActivity would be set to either walk or run within IF/ELSE, so that the value set for sActivity this line
NSString *sActivity = NSLocalizedString(#"activity", #"activity");
would never be read. It might not cause error but analyzer reminded you about this superfluous initialization. Try NSString *sActivity=nil;, see if the warning could be turned down.
You are not using sActivity in if-else blocks, you are simply assigning it values based on decision, So either take it nil string like
sActivity = nil;
or like
NSString *sActivity;
to remove waring .
I recently posted a question regarding some issues I'm having saving data into text fields for an app I'm building in Xcode. The question can be seen here,
Having issues saving data from multiple text fields in Xcode
I received a very helpful answer which helped clue me in to exactly where I was going wrong, but I'm still unsure about the code needed to set the current key when specifying which field to save data from.
Here is the code:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (![self.tField.text isEqualToString:#""]) {
//SET THE CURRENT KEY HERE
[Data setNoteForCurrentKey:self.tField.text];
}
else {
//SET THE CURRENT KEY HERE
[Data removeNoteForKey:[Data getCurrentKey]];
}
if (![self.tField2.text isEqualToString:#""]) {
//SET THE CURRENT KEY HERE
[Data setNoteForCurrentKey:self.tField2.text];
}
else {
//SET THE CURRENT KEY HERE
[Data removeNoteForKey:[Data getCurrentKey]];
}
[Data saveNotes];
}
I added a second detail item property to enable the second text field to be saved, but don't know what code to use to call upon the different detail items. Any help will be greatly appreciated, thanks!
setNoteForCurrentKey: should take two parameters, not one. Then you can pass the key and the value associated with it. Something like:
- (void)setNote:(NSString *)note forKey:(NSString *)key
Using a 'current key' just makes maintenance of that information an issue that you don't need.
In your current code, because you have 2 if statements, you can set the keys as literal values in the code. That isn't very scalable, so going forwards you might want to think about storing your text fields in an array and having another array with the corresponding key names.
I have been attempting to debug a issue with my code, and just came upon an odd phenomenon. Found this in the debug area when a breakpoint was triggered:
Am I correct in observing that there are multiple values for this key: #"6898173"??
What are possible causes of this? I do not set those key-value pairs using the string literal, but by getting a substring of a string retrieved and decoded from a GKSession transmission.
I still have this up in the debug area in xcode, incase theres anything else there that might help.
EDIT:
By request, here is the code that would have created one of the two strings (another was created at an earlier time):
[carForPeerID setObject:[[MultiScreenRacerCarView alloc] initWithImage:[UIImage imageNamed:#"simple-travel-car-top_view"] trackNumber:[[[NSString stringWithUTF8String:data.bytes] substringWithRange:range] intValue]] forKey:[[NSString stringWithUTF8String:[data bytes]] substringFromIndex:9]];
The string in data might look something like this:
car00.0146898173
EDIT:
Code that sends the data:
[self.currentSession sendData:[[NSString stringWithFormat:#"car%i%#%#", [(MultiScreenRacerCarView *)[carForPeerID objectForKey:peerID] trackNumber], speed, [(MultiScreenRacerCarView *)[carForPeerID objectForKey:peerID] owner]] dataUsingEncoding:NSUTF8StringEncoding] toPeers:#[(NSString *)[peersInOrder objectAtIndex:(self.myOrderNumber + 1)]] withDataMode:GKSendDataReliable error:nil];
Sorry its hard to read. Its only one line.
What you're seeing is a debugger "feechure". When you have a mutable dictionary and modify it, the debugger may not show you the correct view of the object.
To reliably display the contents of an NSMutableArray or NSMutableDictionary, switch to the console and type po carForPeerID.