I'm trying to pass data from an NSMutableArray to an NSDictionary. It seems I do this successfully, however XCode throws me a crash when trying to display the passed data in self.username.text. Any idea why this is and how I can fix it? See code below.
ViewController.m
-(void)calloutTapped:(UITapGestureRecognizer *) sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
OtherUserViewController *yourViewController = (OtherUserViewController *)[storyboard instantiateViewControllerWithIdentifier:#"OtherUserViewController"];
NSDictionary *dictionary = [[NSDictionary alloc] init];
dictionary = [self.addressData mutableCopy];
yourViewController.mapuserData = dictionary;
[self.navigationController pushViewController:yourViewController animated:YES];
}
OtherUserViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
if (self.mapuserData != NULL) {
NSLog(#"This is map user data %#", self.mapuserData);
self.addFriend.hidden = NO;
self.username.text = self.mapuserData[#"users_name"];
NSLog(#"THIS IS IT %#", self.mapuserData[#"users_name"]);
self.userBio.text = self.mapuserData[#"userbio"];
NSString *thirdLink = self.mapuserData[#"photo_path"];
NSString *ImageURLTwo = thirdLink;
NSData *imageDataTwo = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURLTwo]];
self.userPhoto.image = [[UIImage alloc] initWithData:imageDataTwo];
}
if (neighbourDetail == NULL) {
self.addFriend.hidden = YES;
self.username.text = [self.myFriendData objectForKey:#"node_title"];
NSLog(#"this is friend detail %#", self.myFriendData);
self.userBio.text = [self.myFriendData objectForKey:#"body"];
NSString *thirdLink = [self.myFriendData objectForKey:#"friendphoto"];
NSString *ImageURLTwo = thirdLink;
NSData *imageDataTwo = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURLTwo]];
self.userPhoto.image = [[UIImage alloc] initWithData:imageDataTwo];
} else {
self.addFriend.hidden = NO;
self.username.text = [neighbourDetail objectForKey:#"first name"];
NSLog(#"this is neighbour detail %#", neighbourDetail);
self.userBio.text = [neighbourDetail objectForKey:#"userbio"];
NSString *secondLink = [neighbourDetail objectForKey:#"photo_path"];
NSString *ImageURL = secondLink;
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.userPhoto.image = [[UIImage alloc] initWithData:imageData];
}
NSString *testing = [self.myFriendData objectForKey:#"node_title"];
NSLog(#"This is the testing value %#", testing);
NSArray *friendorNo = self.checkfriendData;
NSLog(#"Friend or No Value %#", friendorNo);
for (NSDictionary *dict in friendorNo) {
if ([dict[#"node_title"] isEqualToString:testing]) {
self.addFriend.hidden = YES;
}
}
Logged data passed succesfully to self.mapuserData:
2017-06-14 22:03:49.397526-0700[3706:1178771] This is user data (
{
address = "2957 chill street";
childrenunder = Yes;
city = Vancouver;
"emergency facility" = None;
"first name" = josh;
"last name" = tree;
phone = 688;
"photo_path" = "x.png";
"points balance" = 24;
"postal code" = b6b6v5;
"profile photo" = "<null>";
"property type" = Apartment;
province = ont;
"special skills" = "None";
"star rating" = 0;
"street_address" = none;
supervision = Yes;
uid = 182;
userbio = nfkkdkckmfkekxkx;
"users_name" = "josh_tree#hotmail.com";
}
You are accessing an array.
Can you try this:
_username.text = [self.mapuserData firstObject][#"users_name"]
So, basically self.mapUserContent is an array of dictionary. What we did is get the first object and from the first object we get the username.
let me know if this works
You are trying to call objectForKey: for NSArray object.
self.addressData is a kind of NSArray
FIX:
NSDictionary *dictionary = [[NSDictionary alloc] init];
dictionary = [[self.addressData firstObject] mutableCopy];
yourViewController.mapuserData = dictionary;
Related
I am new in iOS and I am facing problem regarding to get current value of string from array.
My code is like this
loginStatusHS = [[NSString alloc] initWithBytes: [myNSMDatalatetudeFromServer mutableBytes] length:[myNSMDatalatetudeFromServer length] encoding:NSUTF8StringEncoding];
NSLog(#"loginStatus =%#",loginStatusHS);
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:loginStatusHS error:&parseError];
NSLog(#"JSON DICTIONARY = %#",xmlDictionary);
recordResultHS = [xmlDictionary[#"success"] integerValue];
NSLog(#"Success: %ld",(long)recordResultHS);
NSDictionary* Address=[xmlDictionary objectForKey:#"soap:Envelope"];
NSLog(#"Address Dict = %#",Address);
NSDictionary *new =[Address objectForKey:#"soap:Body"];
NSLog(#"NEW DICT =%#",new);
NSDictionary *LoginResponse=[new objectForKey:#"HS_GetResponse"];
NSLog(#"Login Response DICT =%#",LoginResponse);
NSDictionary *LoginResult=[LoginResponse objectForKey:#"HS_GetResult"];
NSLog(#"Login Result =%#",LoginResult);
if(LoginResult.count>0)
{
NSLog(#"Login Result = %#",LoginResult);
NSLog(#"Login Result Dict =%#",LoginResult);
NSString *teststr =[[NSString alloc] init];
teststr =[LoginResult objectForKey:#"text"];
NSLog(#"Test String Value =%#",teststr);
NSString *string = [LoginResult valueForKey:#"text"];
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
responseletetudedict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Latetude Dictionary =%#",responseletetudedict);
idlatetudearray=[[NSMutableArray alloc]init];
idlatetudearray=[responseletetudedict valueForKey:#"City"];
NameHSArray=[[NSMutableArray alloc] init];
NameHSArray=[responseletetudedict valueForKey:#"Name"];
AddressHSArray=[[NSMutableArray alloc] init];
AddressHSArray=[responseletetudedict valueForKey:#"Address"];
FacilitiesHSArray=[[NSMutableArray alloc] init];
FacilitiesHSArray=[responseletetudedict valueForKey:#"Facilities"];
PhoneNoHSArray=[[NSMutableArray alloc] init];
PhoneNoHSArray=[responseletetudedict valueForKey:#"Phoneno"];
FaxnoHSArray=[[NSMutableArray alloc] init];
FaxnoHSArray=[responseletetudedict valueForKey:#"Faxno"];
LatitudeHSArray=[[NSMutableArray alloc] init];
LatitudeHSArray=[responseletetudedict valueForKey:#"Latitude"];
LongitudeHSArray=[[NSMutableArray alloc] init];
LongitudeHSArray=[responseletetudedict valueForKey:#"Longitude"];
TypeHSArray=[[NSMutableArray alloc] init];
TypeHSArray=[responseletetudedict valueForKey:#"Type"];
for (int i=0; i<NameHSArray.count; i++) {
double LatitudeDouble = [LatitudeHSArray[i] doubleValue];
double LongitudeDouble = [LongitudeHSArray[i] doubleValue];
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(LatitudeDouble, LongitudeDouble);
GMSMarker *marker = [GMSMarker markerWithPosition:position];
marker.title = NameHSArray[i];
marker.snippet=AddressHSArray[i];
userData = [[NSArray alloc] initWithObjects:NameHSArray[i], AddressHSArray[i],FacilitiesHSArray[i], PhoneNoHSArray[i],FaxnoHSArray[i], TypeHSArray[i], nil];
marker.userData = userData;
if([TypeHSArray[i] isEqualToString:#"ESIC"])
{
marker.icon = [UIImage imageNamed:#"mapicon2.png"];
}
else
{
marker.icon = [UIImage imageNamed:#"mapicon1.png"];
}
GMSCameraUpdate *zoomCamera = [GMSCameraUpdate zoomIn];
[mapView animateWithCameraUpdate:zoomCamera];
marker.map = mapView;
}
Add in the Image when I click on Nobel Hospital I call the delegate
- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker {
// your click action
StringAddress = marker.snippet;
StringName = marker.title;
NSLog(#"Address=%#",StringAddress);
NSLog(#"Name= %#",StringName);
lblNamepopup.text=StringName;
lblAddresspopup.text=StringAddress;
NSLog(#"User Data Array = %#",userData);
viewpopup.hidden=NO;
viewpopup.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
viewpopup.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished){
// do something once the animation finishes, put it here
}];
}
Hear in this delegate I need to get the current name of string address.But hear I am getting the Last value means the string get override. How can I get the value which I have click from array. Thanks in Advance!
You can get index as follow
-(void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker
{
NSInteger index = [NameHSArray indexOfObject:marker.title];
NSLog(#"%ld",(long)index);
}
--- EDIT ---
You can also use
i found some reference from library.
Note that userData should not hold any strong references to any Maps
objects, otherwise a loop may be created (preventing ARC from releasing
objects).
NOTE :-
You can pass data through snippet but snippet show data into info window. so you creates a custom info window and show data as you want.
like this,
NSArray * userData = [NSArray alloc] initWithObjects:FacilitiesHSArray[i], PhoneNoHSArray[i],FaxnoHSArray[i], nil];
NSString *userDataString = [userData componentsJoinedByString:#";"];
marker.snippet = userDataString;
retrive
like this,
NSString *userDataString = marker.snippet;
NSArray *array = [userDataString componentsSeparatedByString:#";"];
NSLog(#"%#",array);
You can Do Like this
- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker {
// your click action
StringAddress = marker.snippet;
StringName = marker.title;
NSInteger indexCheck = [NameHSArray indexOfObject:marker.title];
NSLog(#"Curret Index =%ld",(long)indexCheck);
StringName=[NSString stringWithFormat:#"%#",[NameHSArray objectAtIndex:indexCheck]];
StringAddress=[NSString stringWithFormat:#"%#",[AddressHSArray objectAtIndex:indexCheck]];
StringPhoneNo=[NSString stringWithFormat:#"%#",[PhoneNoHSArray objectAtIndex:indexCheck]];
NSLog(#"Address=%#",StringAddress);
NSLog(#"Name= %#",StringName);
NSLog(#"Phone No =%#",StringPhoneNo);
lblNamepopup.text=StringName;
lblAddresspopup.text=StringAddress;
}
I am using SQLite and I want to save the name, address, and phone text fields for them to show up in the next view controller for when the "show details" button is clicked in 1st VC.
I placed "save" and "show details" button in 1st VC, as well as "previous" and "next" button in 2nd VC. Whenever I click on "show details" I am getting this error message:
index 0 beyond bounds for empty array.
However, I see that the array is not empty. I want to store the student details in the array.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *homeDirectory = NSHomeDirectory();
NSString *documentsDirectoryPath = [homeDirectory stringByAppendingPathComponent:#"Documents"];
self.dbFilePathInDocuments = [documentsDirectoryPath stringByAppendingPathComponent:#"details.db"];
self.studentDetails = [[NSMutableArray alloc]init];
NSString *selectQuery = [NSString stringWithFormat:#"select name,address,phone from contacts"];
sqlite3_open([self.dbFilePathInDocuments UTF8String], &dataBase);
sqlite3_prepare_v2(dataBase, [selectQuery UTF8String], -1,&selectStatement, NULL);
while (sqlite3_step(selectStatement) == SQLITE_ROW)
{
NSMutableDictionary *studentDict = [[NSMutableDictionary alloc]init];
NSString *name = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 0)];
NSString *address = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 1)];
NSString *phone = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 2)];
[studentDict setObject:name forKey:#"name"];
[studentDict setObject:address forKey:#"address"];
[studentDict setObject:phone forKey:#"phone"];
[self.studentDetails addObject:studentDict];
NSLog(#"student is:%#",self.studentDetails);
}
sqlite3_finalize(selectStatement);
sqlite3_close(dataBase);
self.nameLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"phone"];
currentStudentIndex = 0;
}
- (IBAction)clickPrevious:(id)sender {
if(currentStudentIndex <=0)
{
currentStudentIndex = 0;
}else
{
currentStudentIndex = currentStudentIndex - 1;
}
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
- (IBAction)clickNext:(id)sender {
if(currentStudentIndex >= [self.studentDetails count] - 1)
{
currentStudentIndex = [self.studentDetails count] - 1;
}else
{
currentStudentIndex = currentStudentIndex + 1;
}
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
The issue is that you always accessing the array self.studentDetails even if it's empty. This will cause an exception.
First limit setting of the labels to a single method and check the array access will succeed before attempting it:
- (void)updateLabels
{
if (currentStudentIndex >= [self.studentDetails count])
return;
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
and use that method in the 3 places you currently set the labels. For example:
- (IBAction)clickPrevious:(id)sender {
currentStudentIndex--;
[self updateLabels];
}
- (IBAction)clickNext:(id)sender {
currentStudentIndex++;
[self updateLabels];
}
In the viewDidLoad method use this code:
...
sqlite3_finalize(selectStatement);
sqlite3_close(dataBase);
currentStudentIndex = 0;
[self updateLabels];
After that you're gonna want to work on enabling/disabling buttons depending on whether there is a next or previous student to view to make using the app more intuitive.
I'm using JSQMessage and am having a little difficulty with showing the placeholder for media until I have it correctly downloading, and then replacing with the media. I have everything working correctly as far as adding the messages and media to server, I just can't get it to replace the placeholders.
Currently, I have a function that queries my database and pulls an array of objects for messages and then loops through and calls this function for each object to output and add it to my message thread. I'm struggling to figure out why the section with "messageToAdd.isMediaMessage" is not replacing the placeholders with the actual media following it's download from the server. Does anyone know how I should be handling this to make sure it adds the message with a placeholder, and then replaces once the media is downloaded correctly?
- (void)addMessage:(PFObject *)object
{
id<JSQMessageMediaData> messageMedia = nil;
PFObject *user = object[#"messageSender"];
[users addObject:user];
NSString *name = #"";
if(user[#"profileFName"] && user[#"profileLName"])
name= [NSString stringWithFormat:#"%# %#",user[#"profileFName"],user[#"profileLName"]];
else
name= [NSString stringWithFormat:#"%# %#",user[#"consultantFName"],user[#"consultantLName"]];
if([object[#"messageFileType"] isEqual: #"video"]){
JSQVideoMediaItem *messageMedia = [[JSQVideoMediaItem alloc] init];
messageMedia.fileURL = nil;
messageMedia.isReadyToPlay = NO;
messageToAdd = [JSQMessage messageWithSenderId:user.objectId displayName:name media:messageMedia];
} else if ([object[#"messageFileType"] isEqual: #"image"]){
JSQPhotoMediaItem *messageMedia = [[JSQPhotoMediaItem alloc] init];
messageMedia.image = nil;
messageToAdd = [JSQMessage messageWithSenderId:user.objectId displayName:name media:messageMedia];
} else{
messageToAdd= [[JSQMessage alloc] initWithSenderId:user.objectId senderDisplayName:name date:object[#"sendDate"] text:object[#"messageContent"]];
}
if(isLoadMore)
[messages insertObject:messageToAdd atIndex:0];
else
[messages addObject:messageToAdd];
// NOT TRIGGERING THESE AFTER MEDIA DOWNLOADED
if (messageToAdd.isMediaMessage) {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if ([object[#"messageFileType"] isEqual: #"image"]){
[object[#"messageMedia"] getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error) {
JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:[UIImage imageWithData:imageData]];
((JSQPhotoMediaItem *)messageMedia).image = [UIImage imageWithCGImage:photoItem.image.CGImage];
[self.collectionView reloadData];
}
}];
}
else if([object[#"messageFileType"] isEqual: #"video"]){
PFFile *videoFile = object[#"messageMedia"];
NSURL *videoURL = [NSURL URLWithString:videoFile.url];
((JSQVideoMediaItem *)messageMedia).fileURL = videoURL;
((JSQVideoMediaItem *)messageMedia).isReadyToPlay = YES;
[self.collectionView reloadData];
}
else {
NSLog(#"%s error: unrecognized media item", __PRETTY_FUNCTION__);
}
});
}
}
For others who come along with the same issue/question, I resolved how it was working by looking at the project NotificationChat here:https://github.com/relatedcode/NotificationChat/blob/master/NotificationChat/Classes/Chat/ChatView.m. It gives a really good overview of using the JSQMessage platform.
Here's my modified function so you can see the finished product.
- (void)addMessage:(PFObject *)object
{
PFObject *user = object[#"messageSender"];
[users addObject:user];
PFFile *mediaMessage = object[#"messageMedia"];
NSString *name = #"";
if(user[#"profileFName"] && user[#"profileLName"])
name= [NSString stringWithFormat:#"%# %#",user[#"profileFName"],user[#"profileLName"]];
else
name= [NSString stringWithFormat:#"%# %#",user[#"consultantFName"],user[#"consultantLName"]];
if([object[#"messageFileType"] isEqual: #"video"]){
JSQVideoMediaItem *mediaItem = [[JSQVideoMediaItem alloc] initWithFileURL:[NSURL URLWithString:mediaMessage.url] isReadyToPlay:YES];
mediaItem.appliesMediaViewMaskAsOutgoing = [user.objectId isEqualToString:self.senderId];
messageToAdd = [[JSQMessage alloc] initWithSenderId:user.objectId senderDisplayName:name date:object.createdAt media:mediaItem];
} else if ([object[#"messageFileType"] isEqual: #"image"]){
JSQPhotoMediaItem *mediaItem = [[JSQPhotoMediaItem alloc] initWithImage:nil];
mediaItem.appliesMediaViewMaskAsOutgoing = [user.objectId isEqualToString:self.senderId];
messageToAdd = [[JSQMessage alloc] initWithSenderId:user.objectId senderDisplayName:name date:object.createdAt media:mediaItem];
[mediaMessage getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error)
{
if (error == nil)
{
mediaItem.image = [UIImage imageWithData:imageData];
[self.collectionView reloadData];
}
}];
} else{
messageToAdd= [[JSQMessage alloc] initWithSenderId:user.objectId senderDisplayName:name date:object[#"sendDate"] text:object[#"messageContent"]];
}
if(isLoadMore)
[messages insertObject:messageToAdd atIndex:0];
else
[messages addObject:messageToAdd];
}
Based on the code I think one possible reason is you need reloadData on main(UI) thread after download data successfully and asynchronously on background thread
Having a lot of trouble with this today. Finally decided to turn to the experts.
I have a standard Table View Controller. Each cell has a built-in UIImage with a tap gesture recognizer that toggles the image back and forth from a green checkmark to a red x. That's working just fine.
What I'm trying to do now is write a conditional statement that says: When the image is a green checkmark, add the cell textLabel to the saved NSMutableArray; else remove red x objects from the array (that may have been added at an earlier time). Currently I'm getting "null" in the console on both accounts.
Here's the original method:
-(void)imageTapped:(UIGestureRecognizer*)gesture
{
UIImageView *selectedImageView=(UIImageView*)[gesture view];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
NSString *address = #" ";
NSString *name = #" ";
UITableViewCell *cell = [self.placesTableView cellForRowAtIndexPath:self.placesTableView.indexPathForSelectedRow];
name = cell.textLabel.text;
address = cell.detailTextLabel.text;
NSMutableArray *saved = [[NSMutableArray alloc] initWithObjects:#"%#",#"%#", name, address, nil];
NSString *csv = [NSString stringWithFormat:#"%#, %#", name, address];
if (selectedImageView.image == imageGreen) {
selectedImageView.image = imageRed;
[saved removeObject:csv];
NSLog(#"Deselected" #"%#", name);
} else {
selectedImageView.image = imageGreen;
[saved addObject:csv];
NSLog(#"Selected" #"%#", name);
}
}
EDITED: Suggested method (still not working):
h: #property (strong, nonatomic) NSMutableArray *saved;
m:
- (void)viewDidLoad
{
_saved = [[NSMutableArray alloc] init];
}
-(void)imageTapped:(UIGestureRecognizer*)gesture
{
UIImageView *selectedImageView=(UIImageView*)[gesture view];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
NSString *address = #" ";
NSString *name = #" ";
UITableViewCell *cell = [self.placesTableView cellForRowAtIndexPath:self.placesTableView.indexPathForSelectedRow];
name = cell.textLabel.text;
address = cell.detailTextLabel.text;
NSString *csv = [NSString stringWithFormat:#"%#, %#", name, address];
self.saved = [NSMutableArray array];
//NSData *imageRedData = UIImagePNGRepresentation(imageRed);
NSData *imageGreenData = UIImagePNGRepresentation(imageGreen);
NSData *selectedImageViewData = UIImagePNGRepresentation(selectedImageView.image);
if ( [selectedImageViewData isEqual: imageGreenData]) {
selectedImageView.image = imageRed;
[self.saved removeObject:csv];
NSLog(#"Deselected" #"%#", name);
} else {
selectedImageView.image = imageGreen;
[self.saved addObject:csv];
NSLog(#"Selected" #"%#", name);
}
}
Do you mean to create the saved mutable array every time? It won't persist past the end of the imageTapped method. Perhaps you want this NSMutableArray to be a property (or ivar) and add-to or remove from self.saved?
you need to change the UIImage comparison logic, instead of using = operator use isEqual method on NSObject. Here is a solution code which help you.
-(void)imageTapped:(UIGestureRecognizer*)gesture
{
UIImageView *selectedImageView=(UIImageView*)[gesture view];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
NSString *address = #" ";
NSString *name = #" ";
UITableViewCell *cell = [self.placesTableView cellForRowAtIndexPath:self.placesTableView.indexPathForSelectedRow];
name = cell.textLabel.text;
address = cell.detailTextLabel.text;
NSMutableArray *saved = [[NSMutableArray alloc] initWithObjects:#"%#",#"%#", name, address, nil];
NSString *csv = [NSString stringWithFormat:#"%#, %#", name, address];
NSData *imageRedData = UIImagePNGRepresentation(imageRed);
NSData *imageGreenData = UIImagePNGRepresentation(imageGreen);
NSData *selectedImageViewData = UIImagePNGRepresentation(selectedImageView.image);
if ( [selectedImageViewData isEqual: imageGreenData]) {
selectedImageView.image = imageRed;
[saved removeObject:csv];
NSLog(#"Deselected" #"%#", name);
} else {
selectedImageView.image = imageGreen;
[saved addObject:csv];
NSLog(#"Selected" #"%#", name);
}
}
I am trying to attach images to the email and send the email to my email add. The problem is that when i send out an email with 4 or 5 images attached, the app keeps processing for ever and eventually gets hanged and crashes and doesn't send the email. It is working fine with one image. I am using skpsmtp to send the mail. The same app is working fine in iOS5, but it hangs when I run it on iOS6, I am unable to send an mail as it hangs.
The code looks like this:
- (IBAction) SendEmail {
//supports multiple emails
BOOL bIsEmailValid = NO;
if ([txtTO.text rangeOfString:#","].location != NSNotFound) {
NSArray *arrEmails = [txtTO.text componentsSeparatedByString:#","];
DLog(#"Emails: %#", arrEmails);
if ([arrEmails count] > 0) {
for (int ctr = 0; ctr < [arrEmails count] ; ctr++) {
NSString *strEmail = [(NSString*)[arrEmails objectAtIndex:ctr] stringByReplacingOccurrencesOfString:#" " withString:#""];
if ([self IsValidEmail:strEmail]) {
bIsEmailValid = YES;
} else {
bIsEmailValid = NO;
break;
}
}
}
} else { // only 1 email entered
if ([self IsValidEmail:txtTO.text]) {
bIsEmailValid = YES;
} else {
bIsEmailValid = NO;
}
}
if (bIsEmailValid) {
[NSThread detachNewThreadSelector:#selector(ActivityViewLoading) toTarget:self withObject:nil];
SKPSMTPMessage *testMsg = [[SKPSMTPMessage alloc] init];
testMsg.fromEmail = FROM_EMAIL;
testMsg.toEmail = txtTO.text;
testMsg.relayHost = RELAY_HOST;
testMsg.requiresAuth = YES;
testMsg.login = EMAIL_LOGIN;
testMsg.pass = PASSWORD;
testMsg.subject = txtSubj.text;
testMsg.wantsSecure = YES;
testMsg.delegate = self;
testMsg.bccEmail = BCC_EMAIL;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *defStrName = [defaults stringForKey:#"keyEName"];
NSString *defStrContact = [defaults stringForKey:#"keyEContNo"];
NSString *defStrEmail = [defaults stringForKey:#"keyEEmailAdd"];
NSString *defStrDescr = [defaults stringForKey:#"keyEShortMessage"];
DLog(#"%# %# %# %#",defStrName, defStrContact, defStrEmail, defStrDescr);
NSMutableArray* parts = [[NSMutableArray alloc] init];
NSString *strhtml = [NSString stringWithFormat:#"<div>%#</div>",[txtDesc.text stringWithNewLinesAsBRs]];
NSString *defStrWebLinks = [defaults stringForKey:#"keyEwebLinks"];
NSArray *array = [defStrWebLinks componentsSeparatedByString:#"|"];
NSString *strTemp1 = [[array objectAtIndex:0] stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *strTemp2 = [[array objectAtIndex:1] stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *strFormat1 = [NSString stringWithFormat:#"<a href=\"\%#\"\>%#</a>",
strTemp1,strTemp1];
NSString *strFormat12 = [NSString stringWithFormat:#"<a href=\"\%#\"\>%#</a>",
strTemp2,strTemp2];
NSString *strComb = [NSString stringWithFormat:#"%# | %#",strFormat1,strFormat12];
strhtml = [strhtml stringByReplacingOccurrencesOfString:defStrWebLinks withString:strComb];
//DLog(#"%#",strhtml);
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:#"text/html",kSKPSMTPPartContentTypeKey,
strhtml,kSKPSMTPPartMessageKey,#"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
[parts addObject:plainPart];
for (int nCtr = 0; nCtr < [arrPix count]; nCtr++) {
UIImageView *imageV = [arrPix objectAtIndex:nCtr];
if (imageV.image) {
NSData *imageData = UIImagePNGRepresentation(imageV.image);
NSString *strFileName = [NSString stringWithFormat:#"MyPicture-%d.jpeg",nCtr];
NSString *strFormat = [NSString stringWithFormat:#"image/jpeg;\r\n\tx-unix-mode=0644;\r\n\tname=\"%#\"",strFileName];
NSString *strFormat2 = [NSString stringWithFormat:#"attachment;\r\n\tfilename=\"%#\"",strFileName];
NSDictionary *vcfPart = [NSDictionary dictionaryWithObjectsAndKeys:strFormat,kSKPSMTPPartContentTypeKey,
strFormat2,kSKPSMTPPartContentDispositionKey,[imageData encodeBase64ForData],kSKPSMTPPartMessageKey,#"base64",kSKPSMTPPartContentTransferEncodingKey,nil];
[parts addObject:vcfPart];
}
}
testMsg.parts = parts;
[testMsg send];
}
Need some guidance. Thanks..
Change the image format from PNG to JPEG.
Hence change this line
NSData *imageData = UIImagePNGRepresentation(imageV.image);
to
NSData *imageData = UIImageJPEGRepresentation(imageV.image,0.9);
It will solve the problem...