parsing xml for iphone - iphone

can i parse my XML in this method
Blockquote
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// here some instance of XMLparser ??
}
Blockquote
like whenevrr uer press table cell then for detail view i want to pull data at that time only and for that specfic only as i have 8k data so i dont want to parse other data

You have to be careful about runtime performance. If the parse runs really fast, like 50 - 100 ms, it is kind of acceptable performance for me. If it runs too long, like > 1 second, it is absolutely sure that you shouldn't put parsing in that method.
If you talk about pulling data from network and parsing it, it is quite risky and slow for me. If you use synchronous, it will block the UI, if you use asynchronous, what will happen when user going to detail view and don't see anything. If it is just like update old data, it is acceptable to use asynchronous

I've used TouchXML and NSURLConnection in the past for doing these kind of things. You'll probably want to use the asynchronous methods so you don't block the GUI thread during the fetches.

yes i am calling in
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
switch(indexPath.section)
{
case 2:
pragma mark postcode
cell.textLabel.text = aBook.telnumber;
NSLog(#"String = %#",aBook.tel);
NSLog(#"String = %#",aBook.telnumber);
}
tel was defined in sql so that was working correct
now in xml i hav changes that tel to telnumber thats it and commnet that aBook.tel in sql query nothing else
but now its null ... do i need to add xmlparsed elemtns to books in didEndElement in PArsing class??

Related

Display Alert if tableView has no Results

I previously thought I could answer this question with a simple array count (my mistake). I am trying to display an alert to the user id a tableView has no results. I cannot simply place the count in the viewDidAppear method because the web query that populates the JSON and tableView takes a few seconds to populate. I cannot simply place this in:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath {
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows]
lastObject]).row){
//loading complete
}
}
Because nothing gets called in this method if there are no results. Does anyone have any recommendations for this - been searching for over 4 hours and have pulled nearly all my hair out.
Please feel free to un-downvote this questions if it has been made more suitable for SO - this questions massive downvotes have cost me my ability to ask questions...
NSInteger count = [array count];
NSlog("array count : %d",[array count];
This will give you array count in your console.
You cannot check the row count in viewDidAppear because an asynchronous NSURLConnection is used to fetch the JSON data that populates the table view.
The correct way is to call reloadData in connectionDidFinishLoading, after you have updated your data source with the response from the URL request. At that point you know if the number of rows is zero or not, and there is no need to wait for the table view update to complete.

Show Loading Message if table takes a long time

I want to display a "Loading" message if my table is not filled with all the information in 3 seconds. Here is what I want my table to do:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//First time
UITableView *cell = [tableView cellForRowAtIndexPath:indexPath];
//Configure table
//Second Time
}
NSTimeInterval timeDifference = [firstTime timeIntervalSinceDate:secondTime];
if (timeDifference == 3 seconds){
//Display Loading message
}
I think you're approaching the problem wrong in your question. Instead of only showing a loading state if your data loading is taking too long, try always showing the loading state UNTIL the data load operation has completed (hopefully on a background thread which will allow your main UI thread to actually show the loading UI). There are a number of ways to achieve this, the best way for you will depend on your personal preference and existing code.

iPhone SDK SSCollectionView load item from thread

I have an SSCollectionView which is modeled after NSCollectionView and UITableView. It calls a function to load each item at an indexPath.
I want to asynchronously load images into each one of those paths.
- (SSCollectionViewItem *)collectionView:(SSCollectionView *)aCollectionView itemForIndexPath:(NSIndexPath *)indexPath {
....
[self startLoadingItem:item indexPath:indexPath];
return item;
}
-(void)startLoadingItem:(SSCollectionViewItem *)collectionViewItem indexPath:(NSIndexPath *)indexPath
{
[SEThreadInvocation detachNewThreadSelector:#selector(loadItem:indexPath:) toTarget:self withObjects:collectionViewItem,indexPath, nil];
}
SEThreadInvocation is just a subclass of NSThread so that I can send more than one object to a selector.
-(void)loadItem:(SSCollectionViewItem *)collectionViewItem indexPath:(NSIndexPath *)indexPath {
...
collectionViewItem.imageView.image = imageToDisplay;
}
What is happening is that the code initially works, but every time the collection reloads (often) it puts images all over the collection view randomly.
I believe this is because my SSCollectionViewItem is pointing to a different memory location each time and my item is not thread safe, so it is just stamping my images all over the place when they change in memory.
Also, I thought it might be replacing the images in memory, so I replaced it with numbers and the numbers bounce all over the collection view when reloading as well.
How can I make my objects thread safe in this context?
SSToolkit has a sample Catalog project which has a SSCollectionView demo. It loads images in the way you are needing.

NSFetchedResultsController not updating UITableView's section indexes

I am populating a UITableViewController with an NSFetchedResultsController with results creating sections that populate section headers and a section index. I am using the following method to populate the section index:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [fetchedResultsController_ sectionIndexTitles];
}
and now I've run into a problem. When I add a new element to the NSManagedObjectContext associated with the NSFetchedResultsController, the new element is saved and appropriately displayed as a cell in the UITableView ... except for one thing. If the new element creates a new SECTION, the new section index does not show up in the right hand margin unless I pop the UINavigationController's stack and reload the UITableViewController.
I have conformed to the NSFetchedResultsControllerDelegate's interface and manually invoke
[self.tableView reloadSectionIndexTitles];
at the end of both these delegate methods:
controller:didChangeSection...
controller:didChangeObject...
and while I can debug and trace the execution into the methods and see the reload call invoked, the UITableView's section index never reflects the section changes.
Again, the data shows up - new sections are physically visible (or removed) in the UITableView but the section indexes are not updated.
Am I missing something?
Looks like this is a bug we're all having. See http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html for what looks to me like a fairly nasty too-many-lines-of-code solution. I went with this:
- (void)viewWillAppear:(BOOL)animated; {
// This is a dumb hack required by this bug: http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html
[self.tableView reloadData];
}
It may be inefficient but unless you have reams and reams of data it probably won't do any harm. And it's only 1 line of code. So, when apple fixes their bug, you can easily take it out.
Question already 2 months old, but I ran into the same problem today. It seems like -reloadSectionIndexTitles is not working at all, so I tried a couple of potential hacks which of the following works for me:
#implementation UITableView (JKAdditions)
- (UIView *)indexView {
Class indexClass = NSClassFromString(#"UITableViewIndex");
for(UIView *subview in self.subviews){
if([subview isKindOfClass:indexClass]) return subview;
}
return nil;
}
- (void)reloadSectionIndexTitles {
UIView *indexView = [self indexView];
[indexView performSelector:#selector(setTitles:) withObject:[self.dataSource sectionIndexTitlesForTableView:self]];
[indexView setNeedsDisplay];
}
#end
I really have no idea if Apple would reject your App because of this hack, but it seems like the only option for me. Reloading the whole tableView is simply not what I want since I then have to deal with all kinds of animation problems.
I hope this helps anyone having the same problems!
To combine the accepted answer with Alex Reynolds's answer with the delay, just call reloadData with a delay that corresponds to the animation duration, so 0.4 or 0.3 seconds.
In my case, I stick the delayed method call into controller:didChangeSection:atIndex:forChangeType: (it's a Core Data app).
The result, when a section is added or deleted, is the standard animation of the cell, followed by the index being updated when the data is reloaded.
It's ugly and makes me cringe, but I am okay with the result. I also submitted a bug to Apple, #8589547.
Try putting it at the end of -controllerDidChangeContent:, somewhere after [self.tableView endUpdates].
Another thing I do (that works for me, can't guarantee it will work for you) is perform a selector after a very short delay, e.g.:
[self performSelector:(#selector(refreshSectionIndex)) withObject:nil afterDelay:0.2];
// ...
- (void) refreshSectionIndex {
[self.tableView reloadSectionIndexTitles];
}
Core Data and NSFetchedResultsController in particular seem buggy as hell, where delegate table view updates get out of sync with the fetched data, causing the application to crash. I really hope Apple is taking steps to fix the bugs in these frameworks in the 4.0 SDK. It's pretty frustrating.

Limiting App for Free Version (In App Purchase)

I want to set up my app as a free version and unlock it with in app purchases, just so I'll get more exposure. The free version should be limited and therein lies my problem.
My app uses core data heavily and to make the free version, I just want to limit all records displayed to 1 row in each tableview, or if anybody else has any better ideas, those'd work too.
I've been trying to set my numberOfRowsInSection to return 1, but everytime I add something I get a range exception as I'm using a fetchedResultsController. Any ideas?
Here's my section and row code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[fetchedResultsController sections] count];}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];}
Use -setFetchLimit: on the NSFetchRequest. If you set it to 1 then the NSFetchResultController will only give you a single row back.
You could handle this in your didSelectRow method. If the row isn't 0, throw an UIAlertView that explains how you can buy the app to use the full version. This will also show users that more content exists. I seem to recall Apple not liking advertisements for full versions, but I've also seen plenty of it, so I guess it's OK now.
i'm also doing as Marcus has recommended above:
if(!appDelegate.fullVersion){
[fetchRequest setFetchLimit:10];
NSLog(#"only fetching 10 as not full version");
}
I check for full version on appDidFinishLaunching and maintain a BOOL in the appDelegate.
Ensure you add the setFetchLimit: after any predicates you wish to use.