getting user specific data from a webservice to populate a UITableView - iphone

I am trying to populate a UITableView with data for a specific user (his projects) from a webservice, after the user as logged into the app.
for example:
tableData = [[NSMutableDictionary alloc] initWithCapacity:DICTIONARY_INITIAL_CAPACITY];
//CURRENT PROJECT
//get the information from the server
NSArray *currentProject = [[IHMObjectFinderServices sharedIHMObjectFinderServices] getCurrentProjectAsArray:connectedUserId];
if(![currentProject isEqual:[NSNull null]]) {
//put the info in a dictionnary
NSMutableDictionary *currentProjectDictionary = [[NSMutableDictionary alloc] initWithCapacity:PROJECT_DICTIONARY_CAPACITY];
[currentProjectDictionary setObject:[currentProject objectAtIndex:INDEX_PROJECT_NAME] forKey:KEY_PROJECT_NAME];
[currentProjectDictionary setObject:[currentProject objectAtIndex:INDEX_PROJECT_MANAGER] forKey:KEY_PROJECT_MANAGER];
[currentProjectDictionary setObject:[currentProject objectAtIndex:INDEX_PROJECT_TAG] forKey:KEY_PROJECT_TAG];
NSArray *activitiesForProject = [NSArray arrayWithArray:[[IHMObjectFinderServices sharedIHMObjectFinderServices] getAvailableActivities:[currentProjectDictionary valueForKey:KEY_PROJECT_TAG]]];
[currentProjectDictionary setObject:activitiesForProject forKey:KEY_PROJECT_ACTIVITIES];
[tableData setObject:currentProjectDictionary forKey:KEY_CURRENT_PROJECT];
At the moment, my table loads in viewDidLoad method, so the problem is that the user is not yet connected when the table is constructed.
I have read about the reloadData method but I am not sure how to proceed to load the table only once, once the user has logged in. Could someone explain to me what is the correct procedure for this ?
Thanks for your help,
Michael

There should be some kind of call back method when the data for the tableView is available. Just put your reloadData in it.
- (void)dataIsAvailable
{
// ... your code to set the tableData ...
[self.tableView reloadData];
}

Related

IOS - Add subview to certain UICollectionView Cells only

This is the flow of my app: I have UICollectionview with thumbnails of images. User selects images and taps on Save button. Images get saved to camera roll.
This is what I want to do: With a subview I want to mark those cells that user has already tapped on and saved. How do I achieve that?
This is what I have already done....my approach: Obviously I'm missing something and I can't get it resolved.
When user taps on save button I successfully save the IDs of those images to local store using core data. Then, I fetch objects from that entity and put those objects in Array. Now, I'm trying to compare image IDs from fetched array with image IDs in collection view so I can only add subview to those cells where ID's match and that's where i get stuck. I don't know if that's the right approach.
My foolish attempt/s:
This method gets called when user taps on Save Button but it doesn't work properly. I feel as it's randomly adding subviews.
-(void)markSavedImages
{
BOOL isMarked;
NSArray *savedImages = [self fetchSavedPhotos];
NSEnumerator *enumerator = [savedImages objectEnumerator];
NSString *savedImage;
while (savedImage = [enumerator nextObject]) {
if ([[self.eventPhotos valueForKey:#"id"] containsObject:savedImage]) {
isMarked = YES;
}
else
{
isMarked = NO;
}
}
CVCell *cell = [[CVCell alloc]init];
for (NSIndexPath *indexPath in self.livePhotosCollectionView.indexPathsForVisibleItems) {
if (isMarked) {
cell = (CVCell*)[self.livePhotosCollectionView cellForItemAtIndexPath:indexPath];
UIImageView *markedImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"markedCVCell.png"]];
[cell addSubview:markedImage];
[cell bringSubviewToFront:markedImage];
cell.userInteractionEnabled = NO;
}
}
}
The self.eventPhotos is an array that contains image's IDs and paths to server.
Please help me guys, I've been killing my self with this and couldn't find anything on google.
EDIT - as per request
-(NSArray*)fetchSavedPhotos
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Photos" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"eventID ==[c] %#", _eventID];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"No rows returned");
}
NSArray *savedImages = [fetchedObjects valueForKey:#"imageID"];
return savedImages;
}
Some more information....if I output savedImages array in markSavedImages method i do get the array I want to get. Something like this: (1324,2353,2324). Basically array of image IDs.
To begin with, don't add views just to some cells. This usually results in the view being shown on reused cells and multiple copies of the view being added to the cells which looks confusing and is inefficient.
Instead, add the view to every cell. Do it in your cell subclass and make the view publicly visible or add a method to show and hide it. Then do just that. Every time you return a cell, set the visibility of your subview. This ensures that the cell is always configured correctly and that your configuration code is simple.
For disabling the cells use a similar approach, always choose of the cell is enabled or not and set the user interaction enabled on the cell as a whole.
For your data you have a list of the source image ids and a list of the saved image ids. When you configure the cell you know the associated image id. To check if the cell should be tagged and disabled you can do:
BOOL saved = [self.savedImages containsObject:imageId];
(Compare the current id to the list of selected ids, don't do any looping).

NSMutablearray addObject is not working it overwrites data

I'm a beginner to XCode.
1- I have a view with UITableViewCell(FirstViewController)
2- I have another view(SecondViewController) that contains some textfields to get data from user
3- I have to pass this data to the FirstViewController
4- The data is passed successfully to the FirstViewController and successfully added in the TableViewCell
5- but the problem is that....
6- if I add another data, it is added but the previous cell get blanked.
How can I preserve the previous data while saving new one????????
7- temp is variable where data is collected...
8-here (item) is NSMutablearray.. It adds object(temp) to item using
[self.item addObject:temp ];
.. but old value of temp get lost ;(
///my Code
data *temp;
temp =[[data alloc]init];
temp.name=NSLocalizedString(textofsub, #"name");
temp.detail=NSLocalizedString(#"Teacher", #"detail");
temp.image=#"a.jpg";
temp.time=NSLocalizedString(#"8:30", #"time");
[self.item addObject:temp ]; //
[self.mytableView reloadData];
you have to initialize array on viewDidLoad
self.item =[[NSMutablearray alloc]init];

How to get NSString variable value from NSObject to ViewController

I am trying to set up an object to control all of my data so it can set things up in the background to it appears my tableviews load faster than they do now etc.
This is what I am trying to achieve.
I am setting a variable in the NSObject from the secondVC when the tableviewcell is selected like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Access selected cells content (cell.textLabel.text)
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//Parent view logic (sends info back to the correct cell in parent view)
if (parentViewSelectedIndexPath.section == 0)
{
if (parentViewSelectedIndexPath.row == 0)
{
//Predicates restrict the values that will be returned from the query
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like %#",#"MANUFACTURER",cell.textLabel.text];
NSArray *filterArray = [myDataArray filteredArrayUsingPredicate:predicate];
//[[self delegate] setManufactureSearchFields:filterArray withIndexPath:indexPath]; //This is where I pass the value back to the mainview
//Using Object
VehicleControllerNSObject *vehicleControllerNSObject = [[VehicleControllerNSObject alloc] init];
[vehicleControllerNSObject setFirstCell:filterArray];
}
//etc
At the end there you can see the method that is getting set up in the VechicleControllerNSObject which looks like this.
-(void)setFirstCell:(NSArray *)array{
manufactureSearchObjectStringFVC = [[array valueForKey:#"MANUFACTURER"] objectAtIndex:0];
NSLog(#"%#", manufactureSearchObjectStringFVC); // this prints the correct value to the console
}
As you can see this prints the correct output fine.
however I have no idea how to call manufactureSearchObjectStringFVC and pass the value it holds into the uitableviewcell that I would like to pass it in on my firstviewcontroller.
This is what I have for testing atm.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
VehicleControllerNSObject *vehicleControllerNSObject = [[VehicleControllerNSObject alloc] init];
manufactureSearchObjectString = vehicleControllerNSObject.manufactureSearchObjectStringFVC;
NSLog(#"%#", vehicleControllerNSObject.manufactureSearchObjectStringFVC);
}
That nslog prints null..
I have three questions
1, how do I get the correct value into the first valuecontroller.
2, should I be using viewDidAppear like this?.. I think not.. how can I do this better
3, Do you think this is a good way of doing this type of thing, as in the future i would like to use the NSObjectClass to parse info, cache etc all behind the senses leaving the views to just display when the data is ready hopefully helping performance..
Any help would be hugely appreciated as I really want to learn this stuff as i know its important for me to know.
Your question is so beautifully and clearly formatted and diagrammed that it seems a shame to ask you to do a search. But here it is:
Search for Sharing Data between View Controllers
You'll find many good discussions about sharing data between view controllers.
Briefly, though, I can tell you why your code isn't working. In your tableView:didSelectRowAtIndexPath: method, you are creating (alloc/init) a new instance of your VehicleControllerNSObject class each time. Then back in your first view controller on viewDidAppear:, again you are creating (alloc/init) a whole new instance each time.
So you have multiple objects coming and going and they have nothing to do with each other. It's a bit like giving some important information to one person at a bus station and then later randomly picking some other person out and trying to retrieve that same information from her.
So one quick idea would be to create just once instance of your VehicleControllerNSObject (just an aside, that's a bit of a strange name for a class since generally all objective-c objects are descendants of NSObject anyway. I'm just going to call that VehicleController for now)
So let's say you wanted a 'sharedInstance' of VehicleController. You could add a class method to VehicleController to give you a way to easily get that one sharedInstance:
+(VehicleController*)sharedInstance {
static VehicleController *sharedInstance_ = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance_ = [[VehicleController alloc] init];
});
return sharedInstance_;
}
So to get that instance in methods in other classes you can just do something like :
VehicleController *sharedController = [VehicleController sharedInstance];
sharedController.someProperty = someValue;
// and then back in your first view controller, similarly:
VehicleController *sharedController = [VehicleController sharedInstance];
id someValue = sharedController.someProperty;
Again, check the search, many people have had good discussions on this. This is just one approach. I hope it at least makes sense why your code wasn't working.
Hope that helps.
To answer question 3. No.
I think that the best way to do something like this would be to use Core Data and it's NSManagedObject.
A combination of UITableViewController and NSFetchedResultsController that is feed from a Core Data sqlite backing store, if well set would feed and keep your UITableView updated.
It would be to long to describe all in here. So I will stop there.
If you don't want to go with that there is always the possibility to use a shared pointers to a mutable object or to use a singleton object to communicate information between UIViewController.

JSON - Php/SQL iPhone APP Questions/Help

Hey group, first time posting here
I am somewhat new to the JSON/PHP/mySQL world, but been around iPhone designing for the past few years, though this topic of conversation is a while new area I am entering.
I have done JSON iPhone examples that allow me to create a UITableView and display the JSON data into the TableViewCells (CustomCells) and displays the data (NSDictionary)into UILabels
The problem I am having now, is that I want an APP that displays this information from the JSON into just a couple of UILabel's on a regular UIViewController and not a UITableView
any help would greatly be appreciated,
the example I used and learned for JSON and UITABLE was from http://tempered.mobi/%20
I used that example from my app, but incorporated a few other things like CUSTOM cells
however now when the USER selects the specific CELL I want it to load specific data from another JSON file, and cannot get it to load in a UILabel or UITextView in a UIViewController
HELP :-)
Not sure if I completely understand your query, when the user clicks on a table cell you want the app to do a request for data in JSON format and display it in labels on a view? correct?
If so, then I'd modify the didSelectRowAtIndexPath method. Use the index to determine which JSON request to fire, load the results into object/array/dictionary and then set the labels text from this data source.
Apologizes if I mis-understood your question.
Here is my coding to it, this is the XIB that is loaded once the TABLEViewCell is selected, i apologize in advanced for the formatting, I dont know why it is not coming out properly as I am simply copying and pasting from Xcode
.h File, all I added was
IBOutlet UILabel *homeTeam;
IBOutlet UITextView *homeTeam2;
IBOutlet UILabel *awayTeam;
NSArray *rows;
}
#property (retain, nonatomic) NSArray *rows;
(added note: I obviously hooked up the UILabels and UIText View to my labels and text view in that specific XIB) and have tested using the homeTeam.text = #""; (in the Implementation file)to make sure they are functioning properly
.m file
import "CJSONDeserializer.h"
import "JSON.h"
#synthesize homeTeam, awayTeam, awayTeam2;
(void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"http://yourserver.com/yourdata.json"]; // Modify this to match your url.
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url]; // Pulls the URL
//NSLog(jsonreturn);
// Look at the console and you can see what the restults are
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
// In "real" code you should surround this with try and catch
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = [dict objectForKey:#"users"];
[rows retain];
}
NSLog(#"Array: %#",rows); //making NOTE this NSLOG does print my JSON Data grabbed from the SQL Database
awayTeam2.text =[dict objectForKey:#"awayteam"];
awayTeam.text = [dict objectForKey:#"awayteam"];
[jsonreturn release];
CONSOLE: as you can see it grabs my JSON data just fine....
Array: (
{
awayicon = "Brampton.png";
awayteam = Mississauga;
homeicon = "Mississauga.jpg";
hometeam = Brampton;
hscfinal = 10;
id = 1;
}
)

Class variable type gets changed

So in my view controller, I run code to populate an NSArray of Customer (custom class) objects. This custom class has objects that are of ANOTHER custom class called Address (a customer has a billing address and a shipping address). In the view controller when a customer in the list is selected, it passes a new view controller a customer object, like so:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
InfoViewController *customerinfoViewController = [[InfoViewController alloc] initWithStyle:UITableViewStyleGrouped andCustomer:[[[customers objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] retain]];
[self.navigationController pushViewController:customerinfoViewController animated:YES];
[customerinfoViewController release];
}
The first time I visit this view controller while running the application, it works fine. However, when I revisit the view controller, something interesting happens. The application crashes, with unrecognized selector sent to instance 0x00whatever. Using the mouseover debugging feature in xCode, I am finding that the first object of the customer's shipAddress variable has its type changed from NSString to NSIndexPath. This does not happen to the customer's billAddress object. Anyone have any idea what is going on here? It seems like I may be having memory management issues but I would definitely like a confirmation on this before I tear my code apart tracking down all the retains and releases....
EDIT: More information here. with the following code, I have an NSMutableArray at the class level. At each iteration of the loop, I am looping through nodes in XML (which works fine). Every time a new letter is detected as the first letter of the name, I create a new subarray and add the customer to it, thus filling my class-level NSMutableArray (customers) with subArrays of customers for each letter of the alphabet detected. My question is about the retains and releases of the cycling customer object. Clang Static says there is an over-retaining error on the customer, but when I fix it according to Clang, the loop crashes. what gives? Related code below:
DDXMLDocument *rootDoc = [[[DDXMLDocument alloc] initWithData:xmlData options:0 error:nil] autorelease];
NSArray *elems = [rootDoc nodesForXPath:#"QBXML/QBXMLMsgsRs/CustomerQueryRs/CustomerRet" error:nil];
DDXMLNode *node;
sectionTitles = [[[NSMutableArray alloc] initWithCapacity:1] retain]; // Letters for UITableView section titles
NSMutableArray *subArray;
NSString *lastchar = #"A";
NSString *testchar;
int indexCount = -1;
customers = [[[NSMutableArray alloc] initWithCapacity:[elems count]] retain];
Customer *newCust;
for (int i = 0; i < [elems count]; i++) {
node = [elems objectAtIndex:i];
newCust = [[Customer alloc] initWithCustomerRetNode:node];
testchar = [[newCust fullName] substringToIndex:1];
if (i == 0 || ![[testchar uppercaseString] isEqualToString:lastchar]) {
[sectionTitles addObject:testchar];
lastchar = testchar;
indexCount++;
subArray = [[NSMutableArray alloc] initWithCapacity:1];
[customers addObject:subArray];
[subArray release];
[[customers lastObject] addObject:[newCust retain]];
}
else {
[[customers lastObject] addObject:[newCust retain]];
}
[newCust release];
}
NOTE: this code works for the most part, but clang doesn't like it.
EDIT: Addresses in the Customer class are assigned like so (which now does not work after Clang fixes)
...
else if ([tempname isEqualToString:#"BillAddress"])
billAddress = [billAddress initWithAddressNode:tempnode];
else if ([tempname isEqualToString:#"ShipAddress"])
shipAddress = [shipAddress initWithAddressNode:tempnode];
...
It sounds like you are having a over release issue, so yes memory management, you might be overreleasing that array you are storing your objects in.Cant really tell from the snippet of code though. Youll have to go and look through the code and find the source. Also using Clang Static Analyzer might be of help to you.