I have this code:
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
and it is repeated three times
#pragma mark MyURLConnection delegate methods
- (void)connection:(MyURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Response received...");
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
}
- (void)connection:(MyURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"Receiving data...");
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] appendData:data];
}
- (void)connectionDidFinishLoading:(MyURLConnection *)connection {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(#"Request Succeeded! Received %d bytes of data",[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] length]);
//do something with data
NSString *response = [[NSString alloc] initWithData:[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] encoding:NSASCIIStringEncoding];
NSLog(#"HTTP Response: %#",response);
if(connection.tag == APNRegisterURLConnection) {
if([response isEqualToString:kPushNotificationRegistrationSuccess])
[self.userNotifications setObject:[NSNumber numberWithBool:TRUE] forKey:kRegistered];
else if ([response isEqualToString:kPushNotificationReRegistrationSuccess]){
[self.userNotifications setObject:[NSNumber numberWithBool:TRUE] forKey:kRegistered];
NSUUID *udid = [[UIDevice currentDevice] identifierForVendor];
NSString *httpBody = [NSString stringWithFormat:#"udid=%#",udid];
NSString *url = [kRequestURLAddress stringByAppendingString:#"updatenotifications.php"];
[self postRequestForURL:url withParameters:httpBody andTag:UpdateNotificationsURLConnection andPassingData:nil andOptionalMethod:#selector(displayUIActivityIndicatorView)];
}
else {
[self alertWithTitle:#"Error configuring push notifications" andMessage:kUnknownErrorAlertMessage];
}
}
else if(connection.tag == AddNotificationURLConnection) {
if([response isEqualToString:kPushNotificationAdditionSuccess]){
[[self.userNotifications valueForKey:kNotifications] addObject:connection.passingData];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
else {
[self alertWithTitle:#"Error adding notification" andMessage:kUnknownErrorAlertMessage];
}
}
else if(connection.tag == DeleteNotificationURLConnection) {
if([response isEqualToString:kPushNotificationDeletionSuccess]){
[[self.userNotifications valueForKey:kNotifications] removeObjectAtIndex:[connection.passingData row]];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:connection.passingData] withRowAnimation:UITableViewRowAnimationFade];
}
else {
[self alertWithTitle:#"Error deleting notification" andMessage:kUnknownErrorAlertMessage];
}
}
else if(connection.tag == UpdateNotificationsURLConnection) {
if(![response isEqualToString:#"error selecting udid"]){
//load notifications with myurlconnection, since internet is required to add items locally, logical sync is syncing everything to match the database
//sample format for list of notifications
// (int)periodindex (int)timeindex|(int)periodindex2 (int)timeindex2|(int)periodindex3 (int)timeindex3 (sorted by period index
// i.e. --> 0 13|2 6|4 11|4 6|9 4
NSArray *unparsedNotifications = [response componentsSeparatedByString:kNotificationDelimeter];
NSMutableArray *parsedNotifications = [NSMutableArray arrayWithCapacity:[unparsedNotifications count]];
int x;
if(!([[unparsedNotifications objectAtIndex:0] isEqualToString:#""] && [unparsedNotifications count] == 1)) {//no hits in database
NSArray *notificationStringArray;
Notification *parsed;
for (x=0; x<[unparsedNotifications count]; x++) {
notificationStringArray = [[unparsedNotifications objectAtIndex:x] componentsSeparatedByString:kElementDelimeter];
parsed = [Notification withPeriod:[[notificationStringArray objectAtIndex:0] intValue] andTime:[[notificationStringArray objectAtIndex:1] intValue]];
[parsedNotifications addObject:parsed];
}
NSLog(#"number of notifications in database = %d",[parsedNotifications count]);
}
//add missing notifications to array
Notification *value;
for(x=0;x<[parsedNotifications count];x++){
value = [parsedNotifications objectAtIndex:x];
if(![[self.userNotifications valueForKey:kNotifications] containsObject:value]){
[[self.userNotifications valueForKey:kNotifications] addObject:value];
NSLog(#"Adding notification with period:%# and time:%#",[value periodString],[value timeString]);
}
}
//delete objects in local array that are missing from online, reversed in order to remove largest indices and rows so that issue does not arise from looping through an array that has been changed
for(x=[[self.userNotifications valueForKey:kNotifications] count]-1;x>=0;x--){
value = [[self.userNotifications valueForKey:kNotifications] objectAtIndex:x];
if(![parsedNotifications containsObject:value]){
NSLog(#"Deleting notification with period:%# and time:%#",[value periodString],[value timeString]);
[[self.userNotifications valueForKey:kNotifications] removeObjectAtIndex:x];
}
}
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
else
[self alertWithTitle:kDefaultAlertTitle andMessage:kUnknownErrorAlertMessage];
}
[self cleanUpAfterRequest:connection.tag];
[response release];
[connection release];
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
}
-(void)cleanUpAfterRequest:(int)connectionType{
if(connectionType == AddNotificationURLConnection){
self.tableView.allowsSelection = TRUE;
self.tableView.allowsSelectionDuringEditing = TRUE;
}
else if(connectionType == DeleteNotificationURLConnection){
self.view.userInteractionEnabled = TRUE;
}
else if(connectionType == UpdateNotificationsURLConnection){
[[self.view viewWithTag:5] removeFromSuperview];
}
}
- (void)connection:(MyURLConnection *)connection didFailWithError:(NSError *)error {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSString *failingKey = nil;
//IF_PRE_IOS4(failingKey = NSErrorFailingURLStringKey;);
failingKey = NSURLErrorFailingURLStringErrorKey;
NSLog(#"Connection failed! Error - %# %#", [error localizedDescription], [[error userInfo] objectForKey:failingKey]);
[self cleanUpAfterRequest:connection.tag];
[self alertWithTitle:kDefaultAlertTitle andMessage:kDefaultAlertMessage];
[connection release];
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
}
Xcode returns the error "Multiple methods named "setLength" found."
Any ideas on what I should do to fix it?
Assign the results of [self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] to a variable of the proper type. Then call the setLength: method on that variable.
BTW - use modern syntax:
self.receivedData[#(connection.tag)];
The #(connection.tag) replaces the use of [NSNumber numberWithInt:connection.tag] and self.receivedData[xxx] replaces the use of objectForKey:.
Related
Requirement:
We are able to make connection from host device to multiple slave devices. For example, if device A initiate connection to device B and C, the contributor devices can accept peer connection and connected to device A. Here A is master device and B and C are contributors device. Now if B share their songs to A, A can play songs and see songs information. In meantime C will be idle but should connected. When B will finish to play songs, then C can also able to share their songs to device A.
Here are the problem that we have faced to achieve above tasks:
1. As soon as B started sharing songs to A, C got crashed. But A still able to play song shared by B.
array = [[NSMutableArray alloc] initWithObjects:[self.session connectedPeers], nil];
[_session sendData:[NSKeyedArchiver archivedDataWithRootObject:[info mutableCopy]] toPeers:[array objectAtIndex:0] withMode:MCSessionSendDataUnreliable error: &error];
NSLog(#"localizedDescription %#",error);
To overcome from this problem directly pass array without index here toPeers:array. It is working and we are able to share and play songs with device A, but song information not receive to device A.
Here are full code that we are using:
contributor Controller :
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
[self dismissViewControllerAnimated:YES completion:nil];
someMutableArray = [mediaItemCollection items];
counter = 0;
if(someMutableArray.count>1){
BOOL isselectsongone=YES;
[[NSUserDefaults standardUserDefaults] setBool:isselectsongone forKey:#"isselectsongone"];
}
[self showSpinner];
[self someSelector:nil];
}
- (void)someSelector:(NSNotification *)notification {
if(notification && someMutableArray.count>1 && counter <someMutableArray.count-1){
NSDate *start = [NSDate date];
counter=counter+1;
[self.outputStreamer stop];
self.outputStreamer = nil;
self.outputStream = nil;
}
song=[someMutableArray objectAtIndex:counter];
NSMutableDictionary *info = [NSMutableDictionary dictionary];
info=[[NSMutableDictionary alloc] init];
info[#"title"] = [song valueForProperty:MPMediaItemPropertyTitle] ? [song valueForProperty:MPMediaItemPropertyTitle] : #"";
info[#"artist"] = [song valueForProperty:MPMediaItemPropertyArtist] ? [song valueForProperty:MPMediaItemPropertyArtist] : #"";
//NSNumber *duration=[song valueForProperty:MPMediaItemPropertyPlaybackDuration];
int fullminutes = floor([timeinterval floatValue] / 60); // fullminutes is an int
int fullseconds = trunc([duration floatValue] - fullminutes * 60); // fullseconds is an int
[NSTimer scheduledTimerWithTimeInterval:[duration doubleValue]target:self selector:#selector(getdata) userInfo:nil repeats:YES];
}
-(void)getdata {
NSMutableDictionary *info = [NSMutableDictionary dictionary];
info=[[NSMutableDictionary alloc] init];
info[#"title"] = [song valueForProperty:MPMediaItemPropertyTitle] ? [song valueForProperty:MPMediaItemPropertyTitle] : #"";
info[#"artist"] = [song valueForProperty:MPMediaItemPropertyArtist] ? [song valueForProperty:MPMediaItemPropertyArtist] : #"";
NSNumber *duration=[song valueForProperty:MPMediaItemPropertyPlaybackDuration];
int fullminutes = floor([duration floatValue] / 60); // fullminutes is an int
int fullseconds = trunc([duration floatValue] - fullminutes * 60); // fullseconds is an int
info[#"duration"] = [NSString stringWithFormat:#"%d:%d", fullminutes, fullseconds];
MPMediaItemArtwork *artwork = [song valueForProperty:MPMediaItemPropertyArtwork];
UIImage *image = [artwork imageWithSize:CGSizeMake(150, 150)];
NSData * data = UIImageJPEGRepresentation(image, 0.0);
image = [UIImage imageWithData:data];
array = [[NSMutableArray alloc] initWithObjects:[self.session connectedPeers], nil];
MCPeerID* peerID11 = self.session.myPeerID;
NSMutableArray *arr=[[NSMutableArray alloc] initWithObjects:peerID11, nil];
NSLog(#"%#",arr);
if (image)
self.songArtWorkImageView.image = image;
else
self.songArtWorkImageView.image = nil;
self.songTitleLbl.text = [NSString stringWithFormat:#"%# \n[Artist : %#]", info[#"title"], info[#"artist"]];
NSError *error;
[_session sendData:[NSKeyedArchiver archivedDataWithRootObject:[info mutableCopy]] toPeers:[array objectAtIndex:0] withMode:MCSessionSendDataUnreliable error: &error];
NSLog(#"localizedDescription %#",error);
#try {
if(_session && _session.connectedPeers && [_session.connectedPeers count] > 0) {
NSLog(#"%#",[song valueForProperty:MPMediaItemPropertyAssetURL]);
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[song valueForProperty:MPMediaItemPropertyAssetURL] options:nil];
[self convertAsset: asset complition:^(BOOL Success, NSString *filePath) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
if(Success) {
if(image) {
[self saveImage: image withComplition:^(BOOL status, NSString *imageName, NSURL *imageURL) {
if(status) {
#try {
[_session sendResourceAtURL:imageURL withName:imageName toPeer:[_session.connectedPeers objectAtIndex:0]withCompletionHandler:^(NSError *error) {
if (error) {
NSLog(#"Failed to send picture to %#", error.localizedDescription);
return;
}
//Clean up the temp file
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:imageURL error:nil];
}];
}
#catch (NSException *exception) {
}
}
}];
}
#try {
[self hideSpinner];
if(!self.outputStream) {
NSArray * connnectedPeers = [_session connectedPeers];
if([connnectedPeers count] != 0) {
[self outputStreamForPeer:[_session.connectedPeers objectAtIndex:0]];
}
}
}
#catch (NSException *exception) {
}
if(self.outputStream) {
self.outputStreamer = [[TDAudioOutputStreamer alloc] initWithOutputStream:self.outputStream];
//
[self.outputStreamer initStream:filePath];
NSLog(#"%#",filePath);
if(self.outputStreamer) {
[self.outputStreamer start];
}
else{
NSLog(#"Error: output streamer not found");
}
}
else{
//self.outputStream=[[NSOutputStream alloc] init];
self.outputStreamer = [[TDAudioOutputStreamer alloc] initWithOutputStream:self.outputStream];
[self.outputStreamer initStream:filePath];
NSLog(#"%#",filePath);
if(self.outputStreamer) {
[self.outputStreamer start];
}
}
}
else {
[UIView showMessageWithTitle:#"Error!" message:#"Error occured!" showInterval:1.5];
}
});
}];
// }
}
}
#catch (NSException *exception) {
NSLog(#"Expection: %#", [exception debugDescription]);
}
//}
}
HostViewcontroller :
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
NSLog(#"%#",peerID);
NSLog(#"sessions%#",session);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
#try {
// NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:data];
info = [NSKeyedUnarchiver unarchiveObjectWithData:data];
self.songTitleLbl.text = [NSString stringWithFormat:#"%# \n[Duration: %#] [Artist : %#] ", info[#"title"], info[#"duration"], info[#"artist"]];
NSLog(#"eeret%#",self.songTitleLbl.text);
self.songArtWorkImageView.image = nil;
[self showSpinner];
}
#catch (NSException *exception) {
self.songTitleLbl.text = #"Some error occured...\nPlease try again";
self.songArtWorkImageView.image = nil;
}
});
}
Please let us know if I have missed anything here or the better way to achieve the above requirement. Any help really appreciated.
For my pubnub chat app, I am storing some messages locally to keep it from using tons of wifi/data. It seems to work fine, but sometimes the last message is duplicated. Here is my saving,loading,reloading code.
#pragma mark - PubNub manager methods
- (NSString *)parseMessage:(id)message
{
if ([message isKindOfClass:[NSDictionary class]]) {
NSDictionary *messageAsDict = message;
if ([[messageAsDict objectForKey:#"text"] isKindOfClass:[NSString class]]) {
NSString *messageString = [messageAsDict objectForKey:#"text"];
if (messageString || messageString.length > 0) {
return messageString;
} else {
return #"Unable To Parse Message";
}
} else {
return #"Unable To Parse Message";
}
} else if ([message isKindOfClass:[NSString class]]) {
NSString *messageString = message;
if (messageString.length > 0) {
return messageString;
} else {
return #"Unable To Parse Message";
}
} else {
return #"Unable To Parse Message";
}
}
- (void)saveObjects
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *messagesDirectoryPath = [docDir stringByAppendingPathComponent:#"Messaging"];
if (![[NSFileManager defaultManager] fileExistsAtPath:messagesDirectoryPath]) {
[[NSFileManager defaultManager] createDirectoryAtPath:messagesDirectoryPath withIntermediateDirectories:YES attributes:nil error:&error];
}
NSString *messagesPath = [messagesDirectoryPath stringByAppendingPathComponent:messageFile];
NSString *timeTokenPath = [messagesDirectoryPath stringByAppendingPathComponent:timeTokenFile];
NSString *timeTokenString = [NSString stringWithFormat:#"%ld", (long)lastTimeToken];
[messagesArray writeToFile:messagesPath atomically:YES];
[timeTokenString writeToFile:timeTokenPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
}
- (void)loadObjects
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *messagesDirectoryPath = [docDir stringByAppendingPathComponent:#"Messaging"];
NSString *messagesPath = [messagesDirectoryPath stringByAppendingPathComponent:messageFile];
NSString *timeTokenPath = [messagesDirectoryPath stringByAppendingPathComponent:timeTokenFile];
messagesArray = [NSMutableArray arrayWithContentsOfFile:messagesPath];
if (!messagesArray) {
messagesArray = [[NSMutableArray alloc] init];
[self saveObjects];
}
NSString *timeTokenString = [NSString stringWithContentsOfFile:timeTokenPath encoding:NSUTF8StringEncoding error:&error];
if (![timeTokenString isEqualToString:#""]) {
lastTimeToken = [timeTokenString integerValue];
} else {
lastTimeToken = [self currentTimeToken];
[self saveObjects];
}
}
- (void)reloadMessages
{
messagesArray = [[NSMutableArray alloc] init];
//Get all the chats you missed
[self.pnClient historyForChannel:kCHAT_CHANNEL withCompletion:^(PNHistoryResult *result, PNErrorStatus *status) {
// Check whether request successfully completed or not.
if (!status.isError) {
// Handle downloaded history using:
// result.data.start - oldest message time stamp in response
// result.data.end - newest message time stamp in response
// result.data.messages - list of messages
// Get messages
for (id message in result.data.messages) {
[messagesArray addObject:[self parseMessage:message]];
}
// Set timetoken
lastTimeToken = [self parsePNTimeToken:result.data.end];
// Save stuff
[self saveObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messagesTable reloadData];
[self scrollToBottom];
});
} else {
// Request processing failed.
UIAlertController *errorController = [UIAlertController alertControllerWithTitle:#"Error" message:#"Could not recieve messages" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *retryAction = [UIAlertAction actionWithTitle:#"Retry" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[status retry];
}];
[errorController addAction:cancelAction];
[errorController addAction:retryAction];
[self presentViewController:errorController animated:YES completion:nil];
}
}];
}
- (void)addMessage:(PNMessageResult *)message
{
[messagesArray addObject:[self parseMessage:message.data.message]];
lastTimeToken = [message.data.timetoken integerValue] + 1;
[self saveObjects];
}
- (NSInteger)parsePNTimeToken:(NSNumber *)timeToken
{
return trunc([timeToken integerValue] / pow(10, 7));
}
- (NSInteger)currentTimeToken
{
return [[NSDate date] timeIntervalSince1970];
}
- (void)updateLostMessages
{
[self.pnClient historyForChannel:kCHAT_CHANNEL start:[NSNumber numberWithInteger:lastTimeToken] end:[NSNumber numberWithInteger:[self currentTimeToken]] limit:NSIntegerMax withCompletion:^(PNHistoryResult *result, PNErrorStatus *status) {
NSArray *tempResultArray = result.data.messages;
for (id message in tempResultArray) {
[messagesArray addObject:[self parseMessage:message]];
NSLog(#"%#", [self parseMessage:message]);
}
lastTimeToken = [self currentTimeToken] + 1;
[self saveObjects];
[self loadObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messagesTable reloadData];
[self scrollToBottom];
});
}];
}
These methods are pretty straightforward. the parseMessage: one takes a message from whatever and parses the text to be displayed. The saveObjects saves the timeToken and the messages to the disk, and load loads them. The timetoken methods just convert PN timetokens to a less precision format and get the current time token. The updateLostMessages gets all messages from the last messages timetoken to current, and to not get all the messages.
In viewDidLoad I call [self loadObjects] and then [self updateLostMessages] problem is that messages are duplicating! Help appreciated. Also, sorry for long code.
Haha, silly me. I just forgot a + 1 in the reload method. Well, for anyone who wants to use this code to locally store messages instead of getting all of them, here you go. This code stores a timetoken of the last message (+1), and gets all messages from x time token to now.
I have working codes with local sample_data.son but I want to use remote sample_data.json. It's working but I didn't find true way. My code below.
- (void)generateData
{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Add code here to do background processing
//
//
NSError* err = nil;
data = [[NSMutableArray alloc] init];
companyData = [[NSMutableArray alloc] init];
NSString* dataPath = [[NSBundle mainBundle] pathForResource:#"sample_data" ofType:#"json"];
NSArray* contents = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath] options:kNilOptions error:&err];
dispatch_async( dispatch_get_main_queue(), ^{
// Add code here to update the UI/send notifications based on the
// results of the background processing
[contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[data addObject:[NSDictionary dictionaryWithObjectsAndKeys:[[obj objectForKey:#"first_name"] stringByAppendingString:[NSString stringWithFormat:#" %#", [obj objectForKey:#"last_name"]]], #"DisplayText", [obj objectForKey:#"email"], #"DisplaySubText",obj,#"CustomObject", nil]];
[companyData addObject:[NSDictionary dictionaryWithObjectsAndKeys:[obj objectForKey:#"company_name"], #"DisplayText", [obj objectForKey:#"address"], #"DisplaySubText",obj,#"CustomObject", nil]];
}];
});
});
}
#pragma mark MPGTextField Delegate Methods
- (NSArray *)dataForPopoverInTextField:(MPGTextField *)textField
{
if ([textField isEqual:self.name]) {
return data;
}
else if ([textField isEqual:self.companyName]){
return companyData;
}
else{
return nil;
}
}
- (BOOL)textFieldShouldSelect:(MPGTextField *)textField
{
return YES;
}
- (void)textField:(MPGTextField *)textField didEndEditingWithSelection:(NSDictionary *)result
{
//A selection was made - either by the user or by the textfield. Check if its a selection from the data provided or a NEW entry.
if ([[result objectForKey:#"CustomObject"] isKindOfClass:[NSString class]] && [[result objectForKey:#"CustomObject"] isEqualToString:#"NEW"]) {
//New Entry
[self.nameStatus setHidden:NO];
}
else{
//Selection from provided data
if ([textField isEqual:self.name]) {
[self.nameStatus setHidden:YES];
[self.web setText:[[result objectForKey:#"CustomObject"] objectForKey:#"web"]];
[self.email setText:[[result objectForKey:#"CustomObject"] objectForKey:#"email"]];
[self.phone1 setText:[[result objectForKey:#"CustomObject"] objectForKey:#"phone1"]];
[self.phone2 setText:[[result objectForKey:#"CustomObject"] objectForKey:#"phone2"]];
}
[self.address setText:[[result objectForKey:#"CustomObject"] objectForKey:#"address"]];
[self.state setText:[[result objectForKey:#"CustomObject"] objectForKey:#"state"]];
[self.zip setText:[[result objectForKey:#"CustomObject"] objectForKey:#"zip"]];
[self.companyName setText:[[result objectForKey:#"CustomObject"] objectForKey:#"company_name"]];
}
}
I need only change to local parsing code to remote parsing code.
Also you can see original project with local json here
https://github.com/gaurvw/MPGTextField
Not an answer, an example of cleaner code as an answer for formatting.
Original:
[data addObject:[NSDictionary dictionaryWithObjectsAndKeys:[[obj objectForKey:#"first_name"] stringByAppendingString:[NSString stringWithFormat:#" %#", [obj objectForKey:#"last_name"]]], #"DisplayText", [obj objectForKey:#"email"], #"DisplaySubText",obj,#"CustomObject", nil]];
Re-formatted:
NSString *fullName = [NSString stringWithFormat:#"%# %#", obj[#"first_name"], obj[#"last_name"]];
[data addObject: #{
#"DisplayText" : fullName,
#"DisplaySubText" : obj[#"email"],
#"CustomObject" : obj
}];
I want to populate the UITableView with data from a plist file into core data
It's so I easy can update the uitableview in later versions, then I only need to change in the plist life and the core data takes care of the rest. Please tell me if there is a better way...
Anyway this I'm doing here ain't working properly, on the first run it fills the core data BUT the UITableView is empty, then if you close the app totally, also from multi-task-bar thingy and start it up again it now show the uitableview with data
In my app delegate.h I have :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if ( ![userDefaults valueForKey:#"version"] )
{
[self value1];
[self value2];
[self value3];
[self value4];
[self value5];
[self value6];
NSLog(#"running code");
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
// Adding version number to NSUserDefaults for first version:
[userDefaults setFloat:[[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue] forKey:#"version"];
}
if ([[NSUserDefaults standardUserDefaults] floatForKey:#"version"] == [[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue] )
{
/// Same Version so dont run the function
}
else
{
[Hovedmenu MR_truncateAll];
[BarneDaab MR_truncateAll];
[Graviditeten MR_truncateAll];
[MineSygedomme MR_truncateAll];
[Fortalt MR_truncateAll];
[Familien MR_truncateAll];
[self value2];
[self value3];
[self value4];
[self value5];
[self value6];
[self value1];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
NSLog(#"running code agian");
// Update version number to NSUserDefaults for other versions:
[userDefaults setFloat:[[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue] forKey:#"version"];
}
}
and value1 2 3 4 5 6 are almost all the same but from different plists, here's and example
-(void)value1{
NSManagedObjectModel *mom = [self managedObjectModel];
NSDictionary *attrs = [[[mom entitiesByName] objectForKey:#"Hovedmenu"] attributesByName];
NSArray *keyedValues = [[NSArray alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"hovedMenu" ofType:#"plist"]
];
for( NSDictionary *keyedValueDict in keyedValues ) {
NSManagedObject *mObj = [NSEntityDescription insertNewObjectForEntityForName:#"Hovedmenu" inManagedObjectContext:[self managedObjectContext]];
for (NSString *attribute in attrs) {
id value = [keyedValueDict objectForKey:attribute];
if (value == nil) {
// Don't attempt to set nil, or you'll overwite values in self that aren't present in keyedValues
continue;
}
NSAttributeType attributeType = [[attrs objectForKey:attribute] attributeType];
if ((attributeType == NSStringAttributeType) && ([value isKindOfClass:[NSNumber class]])) {
value = [value stringValue];
} else if (((attributeType == NSInteger16AttributeType) || (attributeType == NSInteger32AttributeType) || (attributeType == NSInteger64AttributeType) || (attributeType == NSBooleanAttributeType)) && ([value isKindOfClass:[NSString class]])) {
value = [NSNumber numberWithInteger:[value integerValue]];
} else if ((attributeType == NSFloatAttributeType) && ([value isKindOfClass:[NSString class]])) {
value = [NSNumber numberWithDouble:[value doubleValue]];
}
[mObj setValue:value forKey:attribute];
NSLog(#"Value %# for Key %#", value, attribute);
}
}
NSError *error;
[[self managedObjectContext] save:&error];
}
in my viewcontroller.h
-(void)viewWillAppear:(BOOL)animated{
[self.mainTableView reloadData];
[super viewWillAppear:animated];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
_fetchedResultsController = [Hovedmenu fetchAllGroupedBy:nil withPredicate:nil sortedBy:#"numberRow" ascending:YES delegate:self];
return _fetchedResultsController;
}
I'm using MagicalRecord as well
most likey, from what I can see from your code here is that the contexts which you are using to fetch the values for value1, value2,etc is not the same as the context MagicalRecord creates for you. If you change that context to use the MR_defaultContext, that might update everything properly.
In my project i am using 2 api's in same class. and i want to get data using NSURLRequest,in first api i am getting latitude longitude of places and put these latitude longitude on second url for getting distance between these places but i am getting same distance with each places
here is my code.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
currentLocation = newLocation;
if (currentLocation != nil){
NSString *str=[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=2000&types=%#&sensor=false&key=API Key",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude,strCatText];
[self createTheConnection:str];
//[self createTheConnection1:str1];
arrAllData=[[NSMutableArray alloc]init];
int i;
for (i=0; i<=2; i++)
{
NSString *strname=[[[arr valueForKey:#"results"] objectAtIndex:i] valueForKey:#"name"];
NSString *strvicinity=[[[arr valueForKey:#"results"] objectAtIndex:i] valueForKey:#"vicinity"];
NSString *strRef=[[[arr valueForKey:#"results"]objectAtIndex:i]valueForKey:#"reference"];
NSString *strLat=[[[[[arr valueForKey:#"results"] objectAtIndex:i] valueForKey:#"geometry"] valueForKey:#"location"] valueForKey:#"lat"];
NSString *strLng=[[[[[arr valueForKey:#"results"] objectAtIndex:i] valueForKey:#"geometry"] valueForKey:#"location"] valueForKey:#"lng"];
int j;
for (j=0; j<=0; j++)
{
NSString *str1=[NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%#,%#&sensor=false&mode=driving",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude,strLat,strLng];
//NSLog(#"%#",str1);
[self createTheConnection1:str1];
// if (![strLat isEqual:#"0"]) {
// strDistance=#"";
NSString *strDistance=[[[[[[arr2 valueForKey:#"routes"] objectAtIndex:0] valueForKey:#"legs"] objectAtIndex:0] valueForKey:#"distance"] valueForKey:#"text"];
// NSLog(#"%#",strDistance);
//}
if(strname == nil){
strname = [NSString stringWithFormat:#"%#", [NSNull null]];
}
if(strvicinity == nil){
strvicinity = [NSString stringWithFormat:#"%#", [NSNull null]];
}
if(strRef == nil){
strRef = [NSString stringWithFormat:#"%#", [NSNull null]];
}
if(strDistance == nil){
strDistance = [NSString stringWithFormat:#"%#", [NSNull null]];
}
if (![strDistance isEqual:#"<null>"]) {
arrdata=[[NSMutableArray alloc]initWithObjects:strname,strvicinity,strRef,strDistance, nil];
strDistance=nil;
[arrAllData addObject:arrdata];
}
}
[tblView reloadData];
}
}
-(void)createTheConnection:(NSString*)strUrl
{
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
connections=[[NSURLConnection alloc]initWithRequest:request delegate:self];
if(connections)
{
webData=[NSMutableData data];
}
}
-(void)createTheConnection1:(NSString*)strUrl1
{
NSMutableURLRequest *request1=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[strUrl1 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
connections1=[[NSURLConnection alloc]initWithRequest:request1 delegate:self];
if(connections1)
{
webData1=[NSMutableData data];
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
// //NSLog(#"%#",error);
self.navigationItem.leftBarButtonItem=nil;
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
if (connection==connections) {
[webData appendData:data];
}
if (connection==connections1) {
[webData1 appendData:data];
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
if (connection==connections) {
[webData setLength:0];
}
if (connection==connections1) {
[webData1 setLength:0];
}
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSError *err;
if (connection==connections) {
arr=[NSJSONSerialization JSONObjectWithData:webData options:NSJSONReadingMutableContainers error:&err];
}
if (connection==connections1) {
arr2=[NSJSONSerialization JSONObjectWithData:webData1 options:NSJSONReadingMutableContainers error:&err];
}
}
-(void)barBtnItem1{
MapViewController *mvc =[self.storyboard instantiateViewControllerWithIdentifier:#"mapview"];
[UIView beginAnimations:#"Start" context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[self.navigationController pushViewController:mvc animated:YES];
[UIView commitAnimations];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return arrAllData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"cell"];
UILabel *lblName=(UILabel*)[cell viewWithTag:100];
UILabel *lblAddress=(UILabel*)[cell viewWithTag:101];
UILabel *lblDistance=(UILabel*)[cell viewWithTag:102];
arrData11=[arrAllData objectAtIndex:indexPath.row];
NSString *strName=[NSString stringWithFormat:#"%#",arrData11[0]];
NSString *strAddress=[NSString stringWithFormat:#"%#",arrData11[1]];
NSString *strDistance1=[NSString stringWithFormat:#"%#",arrData11[3]];
if ([strName isEqual:#"<null>"]) {
// lblName.text=#"Loading...";
// lblAddress.text=#"Loading...";
}
else{
lblName.text=strName;
lblAddress.text=strAddress;
lblDistance.text=strDistance1;
}
return cell;
}
You are creating two connection back to back, when they receive data they are calling the delegates but in you app you didn't wait to get the data from first request and then make the second request. I am pretty sure the distance you are getting is the distance of second lat and long.
Make single request for these data and see which distance you are getting. And try to make request one by one. i.e make first request.. get the data .. then make second request. Because they are using same delegate to initialize the data.
EDIT
I am in mobile so I can not help with you code. I'll give a try..
Method A (take parameter that you need to make a url request) {
//Make request with pair of lat and long and necessary datas
}
(void)connectionDidFinishLoading:(NSURLConnection *)connection{
........
//After getting the data
Call method A with next pair of lat long
You can determine next pair by maintaining a global variable.
}
Let me know it that helps...:)