ASIHTTPRequest is not updating the DownloadProgress Delegate - iphone

I am using ASIHTTPRequest to download a file locally to the iDevice.
My download code is as follows
ASIHTTPRequest *download = [ASIHTTPRequest requestWithURL: videoUrl];
[download setCompletionBlock:^{
NSLog(#"Download Success");
// other code
}];
[download setFailedBlock:^{
NSLog(#"Download Failed");
// other code
}];
[download setDownloadProgressDelegate: [item progressDelegate]];
[download startAsynchronous];
NSLog(#"Start Download of %#", [item name]);
The object item holds a reference to a UIProgressView It is show on the screen but never updated.
In an attempt to debug, I subclassed UIProgressView and added the following log
- (void)setProgress:(float)newProgress {
NSLog(#"Current Progress : %f", newProgress);
[super setProgress: newProgress];
}
My Console now shows the progress going from 0.0 to 1.0 over ~50 iterations (nice!) but the uiProgressView doesnt change and at the end the NSLog show 0.5 the default setting for the progress view.
Anyone have an Idea what is happening?
EDIT
UIProgressView is accessed with this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath];
id progressView = [cell viewWithTag:VideoDetailProgressView];
[VideoDownloadManager queueDownloadOfVideo:video progressDelegate: progressView];
}
I have stepped through and watched it appears to keep the correct reference to the UIProgressView throughout
Edit
TableView Methods
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *detailCellIdentifier = #"VideoDetailCell";
static NSString *categoryCellIdentifier = #"VideoCategoryCell";
UITableViewCell *cell = nil;
bool isCategorical = [[self.videoList objectAtIndex: indexPath.row] objectForKey:#"parentName"];
if(isCategorical)
{
cell = [tableView dequeueReusableCellWithIdentifier:categoryCellIdentifier];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:detailCellIdentifier];
}
if (cell == nil && !isCategorical) {
[[NSBundle mainBundle] loadNibNamed:#"VideoDetailCell" owner:self options:nil];
cell = self.videoDetailCell;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5.0, 10.0, 46.0, 46.0)];
[cell addSubview:imageView];
imageView.hidden = !self.canEdit;
imageView.tag = VideoDetailsFavoriteButton;
[imageView release];
self.videoDetailCell = nil;
}
else if(cell == nil && isCategorical)
{
//Different cell
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:categoryCellIdentifier] autorelease];
}
[cell setBackgroundColor:[UIColor clearColor]];
return cell;
}
// Display customization
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *object = [self.videoList objectAtIndex:indexPath.row];
bool isCategorical = [[self.videoList objectAtIndex: indexPath.row] objectForKey:#"parentName"];
if(isCategorical) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.text = [object objectForKey:#"name"];
NSUInteger videoCount = [[Videos sharedVideos] countById: [object objectForKey:#"name"]];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.text = [NSString stringWithFormat: #"%d videos", videoCount];
}
else
{
[[cell viewWithTag:VideoDetailCellTitle] setValue:[object objectForKey:#"name"] forKey:#"text"];
[[cell viewWithTag:VideoDetailCellSubtitle] setValue:[object objectForKey:#"dateAdded"] forKey:#"text"];
[[cell viewWithTag:VideoDetailCellDuration] setValue:[object objectForKey:#"duration"] forKey:#"text"];
UIHTTPImageView *asyncImage = (UIHTTPImageView *)[cell viewWithTag:VideoDetailCellImage];
NSURL *thumbUrl = [NSURL URLWithString:[NSString stringWithFormat: #"%#%#", kRootUrlPath, [object objectForKey:#"image"]]];
[asyncImage setImageWithURL:thumbUrl placeholderImage: [UIImage imageNamed: kLoadingImage]];
asyncImage.clipsToBounds = YES;
UIImageView *editButton = (UIImageView *)[cell viewWithTag:VideoDetailsFavoriteButton];
if ([VideoDownloadManager isQueued: [object objectForKey: #"name"]]) {
[[cell viewWithTag:VideoDetailCellSubtitle] setHidden:YES];
[[cell viewWithTag:VideoDetailProgressView] setHidden:NO];
} else {
[[cell viewWithTag:VideoDetailCellSubtitle] setHidden:NO];
[[cell viewWithTag:VideoDetailProgressView] setHidden:YES];
}
if ([VideoDownloadManager isFavorites: [object objectForKey: #"name"]] || [VideoDownloadManager isQueued: [object objectForKey: #"name"]]) {
editButton.image = [UIImage imageNamed: kFavoritesHighlighted];
} else {
editButton.image = [UIImage imageNamed: kFavoritesEmpty];
}
}
}

Can you check if the update is made in the main thread? (it should be the case if you're using the latest version of ASIHTTPRequest)
NSLog(#"Current Progress : %f (main thread=%d)", newProgress, [NSThread isMainThread]);
If it doesn't help, can you show the code that is using the UIProgressView in the view?

Thanks for everyones help. You guys guided me to then answer. My cell was not correctly being assigned a reuseIdentifier
this was causing the whole issue.

Related

Update Data and show it on UITableView iOS

I have a problem: update data in UITableView. I want to get new data from parseXML that response from Server and them update new data to UITableView. **I used beloww code, but it does not show new data on Table View. I wrote a UpdateArray() function to check new data and then I compare 2 Array,if diff [Array count] then I call [tableview reloadData];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [temp count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 90;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *FileNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
FileNameLabel.backgroundColor = [UIColor clearColor];
FileNameLabel.font = [UIFont fontWithName:#"Helvetica" size:16];
FileNameLabel.font = [UIFont boldSystemFontOfSize:16];
FileNameLabel.textColor = [UIColor blackColor];
NSLog(#"Reseversed TEMP array %#",temp);
FileNameLabel.text =[temp objectAtIndex:indexPath.row];
[cell.contentView addSubview: FileNameLabel];
[FileNameLabel release];
UILabel *UploadTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 20, 300, 25)];
UploadTimeLabel.backgroundColor = [UIColor clearColor];
UploadTimeLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
UploadTimeLabel.textColor = [UIColor grayColor];
UploadTimeLabel.text = [UploadTimeArray objectAtIndex:indexPath.row];
[cell.contentView addSubview: UploadTimeLabel];
[UploadTimeLabel release];
UILabel *CompleteLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 12, 170, 25)];
CompleteLabel.backgroundColor = [UIColor clearColor];
CompleteLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
CompleteLabel.textColor = [UIColor darkGrayColor];
CompleteLabel.text =#"Completed";
CompleteLabel.textAlignment = NSTextAlignmentRight;
[cell.contentView addSubview: CompleteLabel];
[CompleteLabel release];
}
return cell;
}
UpdateArray()
-(void)updateArray{
while (loop)
{
[NSThread sleepForTimeInterval:4.0];
[FileCompletedArray removeAllObjects];
// [temp removeAllObjects];
....
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success");
NSString * parsexmlinput = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Response in Loop CompleteView: %#", parsexmlinput);
// dispatch_async(dispatch_get_main_queue(), ^{
[self parseXMLFile:parsexmlinput];
NSLog(#"File Completed array: %#", FileCompletedArray);
NSLog(#"File Temp out array: %#", temp);
NSLog(#"File Completed count: %lu",(unsigned long)[ FileCompletedArray count]);
NSLog(#"File Temp out count: %lu", (unsigned long)[temp count]);
// NSLog(#"State: %#", state);
if([FileCompletedArray count ] != [temp count])
{
[temp removeAllObjects];
temp= [FileCompletedArray mutableCopy];
[_tableView reloadData];
}
else
{
NSLog(#"2 array equal");
}
//});
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", error);
}
];
[httpClient enqueueHTTPRequestOperation:operation];
}
}
Can you help me? Thanks in advance.
I dont See that you call reloadData.
EDIT:
You must check that
1-Temp is having objects i mean that [temp count] is not returning zero.
2-The if condition that checks the two arrays is triggered . I mean that reload data is called.
3-You can make a breakpoint after cell.contetview addsubview and check what the cell contain now?
before you call
[_tableView reloadRowsAtIndexPaths:[_tableView indexPathsForVisibleRows]
withRowAnimation:UITableViewRowAnimationNone];
you have to call
[_tableView beginUpdates];
...
[_tableView endUpdates];
or call
[_tableView reloadData];
If you refresh table view then try this line & check:
[[self mytableview] reloadData];
mytableview is obj of tableview you give here your tableview object.

Objective-C: 2 UItableViews displayed

I am sorry for pasting a big chunk of code but i really want to get it work;
This app is supposed to be placing a UItableView on a screen.
Somehow this code is calling tableview methods twice and creating duplicate tables.
Do you have any suggestion what I can do to fix this behaviour?
Thanks in advance.
UITableView:
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"-------------numberOfRowsInSection---------------");
NSLog(#"qtext =%d",[qtext count]);
return [qtext count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{
return 1;
}
-(void)insertDeviders{
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
myLabel.text = #"About you";
[cell addSubview:myLabel];
}
//Return cellheight
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSLog(#"-------------heightforrowatindexpath---------------");
dict = [qtext objectAtIndex:[indexPath row]];
NSDictionary *dict2 = [qtype objectAtIndex:[indexPath row]];
type = [[dict2 allKeys] objectAtIndex:0];
NSString *text = [[dict allKeys] objectAtIndex:0];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 44.0f);
thisheight= height + (CELL_CONTENT_MARGIN * 2) + 40;
NSLog(#"thisheight=%d",thisheight);
NSString *q = [NSString stringWithFormat:#"%d", thisheight];
[arrAllheight addObject:[NSString stringWithFormat:#"%#",q]];
if([type isEqualToString:#"devider"]){thisheight=28;}
NSLog(#"dict=%#",dict);
NSLog(#"thisheight=%d",thisheight);
return thisheight;
}
Populate cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"-------------cellForRowAtIndexPath---------------");
cell_id = [qid objectAtIndex:[indexPath row] ];
static NSString *CellIdentifier = #"Cell";
label = nil;
cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// if(![cell_id intValue]==0){
dict = [qtext objectAtIndex:[indexPath row]];
celltext = [NSString stringWithFormat:#"%#\n\n\n",[[dict allKeys] objectAtIndex:0]];
dict = [qtype objectAtIndex:[indexPath row]];
type = [[dict allKeys] objectAtIndex:0];
//place the question
cell.textLabel.text = celltext;
// NSLog(#"row=%#",[indexpath row]);
if([type isEqualToString:#"devider"]){
[self configureDevider];
}else{
[self configureCell];
}
if([cell_id intValue] == ([qid count])){
tabledone = #"Yes";
}
tableView.backgroundColor=[UIColor clearColor];
tableView.opaque=NO;
tableView.backgroundView=nil;
NSString *a = [arrAllheight objectAtIndex:[indexPath row]];
// NSLog(#"allheight=%d",allheight);
allheight +=thisheight;
thisheight =[a intValue];
if(![tabledone isEqualToString:#"Yes"])
if([type isEqualToString:#"YN"]){
DCRoundSwitch *ynSwitch = [[DCRoundSwitch alloc] initWithFrame:CGRectMake(220,thisheight-40,80,27)] ;
ynSwitch.onText=#"Yes";
ynSwitch.offText=#"No";
[answers addObject:ynSwitch];
[cell addSubview:ynSwitch];
[ynSwitch setTag:[cell_id intValue]];
[ynSwitch addTarget:self action:#selector(setAnswersForRoundSwitches:) forControlEvents:UIControlEventValueChanged];
NSLog(#"cell_id=%#", [dicAnswers objectForKey:[NSString stringWithFormat:#"", cell_id]]);
// if[dicAnswers objectForKey:[NSString stringWithFormat:#"", cell_id]]){}
i++;
}else if([type isEqualToString:#"freetext"]){
//When the done button was clicked, remove the keybords from the screen
[self makeTextField];
[rtxtfield addTarget:self action:#selector(setAnswersfortextFields:) forControlEvents:UIControlEventEditingDidEndOnExit];
// [rtxtfield value];
}else if([type isEqualToString:#"dropdown"]){
picc = [picker_array objectForKey:[[NSString alloc] initWithFormat:#"%d",cell_id]];
//Choose an array for this textField
// [self getPickerArray];
[self makeTextField];
//[rtxtfield addTarget:self action:#selector(setAnswersfortextFields:) forControlEvents:UIControlEventEditingDidEndOnExit];
//When the done button was clicked, remove the keybords from the screen
[rtxtfield addTarget:self action:#selector(textFieldReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
//Get the tag for picker
[rtxtfield addTarget:self action:#selector(getTag:) forControlEvents:UIControlEventTouchDown];
//Display picker
[rtxtfield addTarget:self action:#selector(acsheet:) forControlEvents:UIControlEventTouchDown];
//set Tag for the textField
[rtxtfield setTag:[cell_id intValue]];
NSLog(#"rtxtfield tag=%d",rtxtfield.tag);
}
if([type isEqualToString:#"devider"]){
[self caliculateHeightofCell];
}else{
[self caliculateHeightofCell];
}
return cell;
}
get tag name when user finished editing:
-(void)getTag:(UITextField*)txtf{
NSLog(#"-------------getTag-------------");
whichTextTag = txtf.tag;
picc = [picker_array objectForKey:[[NSString alloc] initWithFormat:#"%d",whichTextTag]];
[self getPickerArray];
}
lifecycle:
- (void)viewDidLoad
{
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"main_bg.png"]];
// [super viewDidLoad];
dicAnswers = [NSMutableDictionary dictionary];
[self getClaimQuestions];
[self getSchemeLimitThreshold];
[self getShchemeLimit];
tabledone=#"";
[self getQuestionsAY];
// [self getQuestionsH];
[self getCountries];
// [self getQuestions];
[self getITClass];
self->table.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self->table.separatorColor = [UIColor lightGrayColor];
[self placeNextButton];
// tabledone =#"Yes";
}
Are you using interface builder? Then check if you have not connected the tableview to the controller twice in IB - once as the view outlet and again as table.
I haven't tested your code as I don't have your data nor do I see how it's being built but looking through your code I see several problems. The most dire one though is you may not understand how dequeueReusableCellWithIdentifier is supposed to work. You appear to be defining the variable cell outside of your tableView:cellForRowAtIndexPath: which means that you could be overwriting that cell every time. I'd suggest you read up on how the dequeueReusableCellWithIdentifier is supposed to work. Have a look here: iPhone - What are reuseIdentifiers (UITableViewCell)?.

App crashes after custom cell is created 250 times

I use a custom cell in my app. When a user taps a table row, a custom cell appears:
#import "SonaraamatuKontroller.h"
#import "TolkegaLahter.h"
//Lahtris kasutatava teksti fondi suurus
#define FONT_SIZE 14.0f
//Tabelilahtri laius
#define CELL_CONTENT_WIDTH 320.0f
//Tabeli sisu äärise kaugus lahtri servadest
#define CELL_CONTENT_MARGIN 5.0f
#implementation SonaraamatuKontroller
#synthesize sonaraamatuSisukord=sonaraamatuSisukord;
#synthesize sonaraamatuTabel;
#synthesize valitudLahtriIndexPath;
#synthesize tolkegaLahter;
#synthesize audioPleier;
#synthesize sonaraamatuFailinimi;
#synthesize sonaraamatuNavribaNimi;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *error;
NSPropertyListFormat format;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:sonaraamatuFailinimi ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:localizedPath];
NSArray *sisukordData = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (sisukordData) {
self.sonaraamatuSisukord = [NSMutableArray arrayWithCapacity:[sonaraamatuSisukord count]];
for (NSDictionary *sisukordDictionary in sisukordData) {
[self.sonaraamatuSisukord addObject:sisukordDictionary];
}
}
self.navigationItem.title=sonaraamatuNavribaNimi;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
//Teise vaatesse liikumisel pannakse audiopleier seisma
[audioPleier stop];
// Release anything that can be recreated in viewDidLoad or on demand.
// e.g. self.myOutlet = nil;
}
#pragma mark -
#pragma mark UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//Loeme tabeli sektsioonide arvu - kuna praegusel juhul on sisukorras ainult üks liige (sõnaraamat "Item 0"), siis on ka sektsioone üks
return [sonaraamatuSisukord count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//Loeme vastavas sektsioonis asuvate ridade arvu
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:section] objectForKey:#"Items"];
return [sisukordItems count];
}
- (CGFloat) tableView : (UITableView *) tableView
heightForRowAtIndexPath: (NSIndexPath *) indexPath {
if(valitudLahtriIndexPath != nil
&& [valitudLahtriIndexPath isEqual:indexPath] )
return 95;
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
NSString *text = [sisukordItem objectForKey:#"Valjend"];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 25.0f);
return height + (CELL_CONTENT_MARGIN * 2);
}
#pragma mark -
#pragma mark UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if((valitudLahtriIndexPath != nil)
&& [valitudLahtriIndexPath isEqual:indexPath]
)
{ //NSLog (#"ValitudPath: %#", valitudLahtriIndexPath);
static NSString *TolkegaLahtriTunnus = #"TolkegaLahter";
TolkegaLahter *cell = (TolkegaLahter *)[tableView dequeueReusableCellWithIdentifier:TolkegaLahtriTunnus];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TolkegaLahter" owner:self options:nil];
cell = tolkegaLahter;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
//Lisame gradiendi:
CAGradientLayer *gradient = [CAGradientLayer layer];
[gradient setCornerRadius:9.0f];
//[gradient setMasksToBounds:YES];
//[gradient setBorderWidth:0.8f];
//[gradient setBorderColor:[[UIColor darkGrayColor] CGColor]];
gradient.frame = cell.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.122 green:0.2 blue:1 alpha:0.95] CGColor], (id)[[UIColor colorWithRed:0.041 green:0.1 blue:0.33 alpha:0.95] CGColor],(id)[[UIColor colorWithRed:0.122 green:0.2 blue:1 alpha:0.95] CGColor], nil];
gradient.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.48],[NSNumber numberWithFloat:1.0], nil];
[cell.layer insertSublayer:gradient atIndex:0];
}
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
cell.valjend.text=[sisukordItem objectForKey:#"Valjend"];
cell.tolge.text=[sisukordItem objectForKey:#"Tolge"];
[sonaraamatuTabel scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
self.tolkegaLahter = nil;
return cell;
}
static NSString *CellIdentifier = #"Cell";
//Loome lahtrisse labeli
UILabel *label = nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//Esialgu on label tühi (asub punktis 0,0 ning on suurusega 0,0)
label = [[UILabel alloc] initWithFrame:CGRectZero];
//Määrame reavahetuse stiili
[label setLineBreakMode:UILineBreakModeWordWrap];
//Minimaalne fondi suurus on ülal defineeritud konstant
[label setMinimumFontSize:FONT_SIZE];
//Esialgu on ridade arv 0
[label setNumberOfLines:0];
//Määrame fondi. Selle suuruseks on ülal defineeritud konstant
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
[label setTag:1];
//Lisame labelile piirid, et programmeerimise käigus oleks paremini näha, kuhu see lahtris paigutub
//[[label layer] setBorderWidth:2.0f];
[[cell contentView] addSubview:label];
[label release];
}
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.selectedBackgroundView=[[[UIView alloc] init] autorelease];
cell.selectedBackgroundView.backgroundColor=[UIColor colorWithRed:0.537 green:0.18 blue:0.122 alpha:1.0];
//Loome andmemassiivi sisukord objektidest (tuntakse ära võtme "Items" abil) andmemassiivi sisukordItems
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
//Loome andmemassiivi sisukordItems objektidest sõnaraamatud sisukordItem
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
//Igas lahtris kuvatakse sellele vastavas sõnaraamatus sisalduva objekti "Valjend" väärtus
NSString *text = [sisukordItem objectForKey:#"Valjend"];
//Sarnaselt lahtri kõrguse arvutamisele heightForRowAtIndexPath meetodis arvutame ka labeli
//kõrguse (sellele ei liideta ääriste kaugusi)
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
//Hangime labeli juhul kui see on nil (ja tegu ei ole vaate esialgse initsieerimisega ehk lahter ei ole nil)
if (!label)
label = (UILabel*)[cell viewWithTag:1];
//Seame labeli teksti
[label setText:text];
//Seame labeli piirjooned
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 25.0f))];
label.textColor=[UIColor blackColor];
label.font=[UIFont systemFontOfSize:14];
label.backgroundColor=[UIColor clearColor];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.valitudLahtriIndexPath = indexPath;
if(valitudLahtriIndexPath != nil //Kui see väärtus on tõene,
&& [valitudLahtriIndexPath isEqual:indexPath]) {
[self.sonaraamatuTabel reloadData];
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
NSString*heliFailinimi=[sisukordItem objectForKey:#"HeliFailinimi"];
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
NSString *taustaHeliPath = [[NSBundle mainBundle] pathForResource:heliFailinimi ofType:#"m4a"];
[audioPleier stop];
NSURL *taustaHeliURL = [NSURL fileURLWithPath:taustaHeliPath];
NSError *error;
audioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error];
[audioPleier setDelegate:self]; // We need this so we can restart after interruptions
[audioPleier play];
}
}
- (void)viewWillAppear:(BOOL)animated
{
NSIndexPath*selection = [self.sonaraamatuTabel indexPathForSelectedRow];
if (selection)
[self.sonaraamatuTabel deselectRowAtIndexPath:selection animated:YES];
[self.sonaraamatuTabel reloadData];
}
- (void)dealloc {
[valitudLahtriIndexPath release];
[sonaraamatuSisukord release], sonaraamatuSisukord=nil;
[audioPleier release];
[sonaraamatuFailinimi release];
[sonaraamatuNavribaNimi release];
[super dealloc];
}
#end
After 250 taps the app crashes and I get the message:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle (loaded)' with name 'TolkegaLahter''
What could be the reason of this behaviour? A memory leak somewhere?
EDIT
It was about the AVAudioPlayer, which was created again and again, but not released.
So, I replaced
audioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error];
with
AVAudioPlayer*ajutineAudioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error];
self.audioPleier=ajutineAudioPleier;
[ajutineAudioPleier release];
Is the code in your question the cellForRowAtIndexPath method? It isn't clear from your question whereabouts this code is or when it is executed.
If it is (or, for some of these, even if it isn't) there are a couple of problems with it:
You aren't returning the cell if the dequeue method brings you something back
You aren't configuring the cell if the dequeue method brings you something back
Which leads me to expect that you haven't set the reuse identifier in your custom cell subclass in interface builder
Which means you are creating a new cell each time which could give you a crash if you have a sufficient number of cells
The scrolling call seems odd (this would only be odd if this was your cellForRowAtIndexPath method)
If you are repeatedly loading from nibs you may want to check out UINib as well.
EDIT
After looking at your full code, I think the problem is your audio player, you are creating and configuring a new one every time the cell is selected and this is leaking.
You should just set up the audio player on your viewDidLoad, and just tell it to play the specific sound when you select the cell.
Try to replace
[[NSBundle mainBundle] loadNibNamed:#"TolkegaLahter" owner:self options:nil];
cell = tolkegaLahter;
to
cell = [[[TolkegaLahter alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: TolkegaLahtriTunnus] autorelease];
self.tolkegaLahter = [[[NSBundle mainBundle] loadNibNamed:#"TolkegaLahter" owner:self options:nil] lastObject];
cell = self.tolkegaLahter;

Why aren't my NSMutableArray objects being added to the UITableView straight away?

I have an NSMutableArray with objects within it and I use the following code to add/remove objects from the UITableView. It works but only after closing and relaunching the app, not straight away. Why is this? Here is my code (maincelltext is the title in the cell and subtitlecelltext is the subtitle):
maincelltext = [[NSMutableArray alloc] init];
subtitlecelltext = [[NSMutableArray alloc] init];
[maincelltext addObject:#"TITLE"];
[subtitlecelltext addObject:#"SUBTITLE TEST"];
EDIT: Here is my UITableView code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.font = [UIFont fontWithName:#"HelveticaBold" size:16.0];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.numberOfLines = 1;
// Configure the cell.
UIImage *cellImage = [UIImage imageNamed:#"warning.png"];
CGRect cropRect = CGRectMake(0.0, 0.0, 12.0, 12.0);
CGImageRef croppedImage = CGImageCreateWithImageInRect([cellImage CGImage], CGRectMake(0.0f,0.0f,cellImage.size.width,cellImage.size.height));
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:cropRect];
[myImageView setImage:[UIImage imageWithCGImage:croppedImage]];
CGImageRelease(croppedImage);
[self.view addSubview:myImageView];
cell.imageView.image = cellImage;
NSString *subjectString = [maincelltext objectAtIndex: [indexPath row]];
cell.textLabel.text = subjectString;
NSString *subtitle = [subtitlecelltext objectAtIndex: [indexPath row]];
cell.detailTextLabel.text = subtitle;
if(maincelltext.count == 0){
NSString *notabledata = [NSString stringWithFormat:#"No Dates Set"];
[maincelltext addObject:notabledata];
}
return cell;
}
Thanks!
you need to tell the UITableView that it needs to insert the rows. First determine the index in the array the new object(s) are now at, then tell the UITableView to insert the rows like this:
NSIndexPath *indexPathOfNewObject=[NSIndexPath indexPathForRow: newObjectIndex section:0];
NSArray *indexPathArray=[NSArray arrayWithObject: indexPathOfNewObject];
[self.tableView beginUpdates];
// Note that UITableViewRowAnimationAutomatic is for iOS5 only.
[self.tableView insertRowsAtIndexPaths: indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
by using this method, you will get the cool animation effect on the tableView.
Alternatively, you could just call [self.tableView reloadData] and it will just reload all the data.
Good luck!
Just do a [myTableView reloadData]; after you did an [myArray addObject:myObject]; and you should be fine.

iphone slow navigation due to data load

I'm newbie to objective-c . My problem is slow navigation between controllers.
When I jump from one controller to another it's really slow, because it gets data from the service, parse it and then display it. All this takes around 4-5 secs.
Now I've put all this data fetching in loadView of my DetailController. Is there anyway that I show the controller first and then display the data. Because as of now, when I select a row on my root controller, it shows activity and stays on root controller and then it navigates to the DetailController.
So it loads the data first and then displays it. Is there anyway that I can reverse this process, show the controller first and then display it..
this is what I'm doing
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DataCollection *collection = [DataCollection sharedObject];
Product *tempProduct = [[collection popularProducts] objectAtIndex:row] ;
ProductDetailViewController *tempProductDetail = [[ProductDetailViewController alloc] init];
tempProductDetail.homeViewProduct = tempProduct;
[tempProductDetail release];
}
and then the Detail Controller
- (void)loadView {
[super loadView];
// here's all the data loading and parsing ... which takes time
}
//Here's the method for downloading the data, I'm using a REST service to get all the data.
- (void) getProductData:(NSString*)productId{
NSMutableString *specificURL = [[NSMutableString alloc] initWithString:#"GetProductPage?id="];
[specificURL appendFormat:#"%#",productId];
[specificURL appendFormat:#"&dataSources=&accountId=&companyId=&version=1&cultureCode=sv&currencyId=2&format=json"];
NSDictionary *serverCategories = [[NSDictionary alloc] initWithDictionary:[appRequestController proceesRequest:specificURL]];
NSArray *categories = [[[serverCategories objectForKey:#"DataSources"] objectAtIndex:0] objectForKey:#"Items"];
[serverCategories release];
if ([[productsArray objectAtIndex:j] objectForKey:#"Name"] != [NSNull null]) {
[product setProductName:[[productsArray objectAtIndex:j] objectForKey:#"Name"]];
}
else {
[product setProductName:#""];
}
if ([[productsArray objectAtIndex:j] objectForKey:#"ThumbnailImage"] != [NSNull null]) {
[product setProductImage:[[productsArray objectAtIndex:j] objectForKey:#"ThumbnailImage"]];
}
else {
[product setProductImage:#""];
}
if ([[productsArray objectAtIndex:j] objectForKey:#"Price"] != [NSNull null]) {
[product setProductPrice:[[productsArray objectAtIndex:j] objectForKey:#"Price"]];
}
else {
[product setProductPrice:#""];
}
[[collection popularProducts] addObject:product];
[product release];
}
I've copy pasted junks of the code so that you can get an idea how I'm getting the data. Below is the code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *MyIdentifier = #"mainMenuIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
[cell setSelectedBackgroundView:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"highlightstrip.png"]]];
}
UILabel *productNameLbl = [[UILabel alloc] initWithFrame:CGRectMake(90, 8, 200,10)];
[productNameLbl setText:[NSString stringWithString:[[[[DataCollection sharedObject] popularProducts]objectAtIndex:indexPath.row] productName]]];
[productNameLbl setFont:[UIFont boldSystemFontOfSize:12.0]];
[cell addSubview:productNameLbl];
[productNameLbl release];
UILabel *productSubLbl = [[UILabel alloc] initWithFrame:CGRectMake(90, 22, 190,40)];
[productSubLbl setText:[NSString stringWithString:[[[[DataCollection sharedObject] popularProducts]objectAtIndex:indexPath.row] productSubHeader]]];
[productSubLbl setTextColor:[UIColor colorWithRed:102.0/255.0 green:102.0/255.0 blue:102/255.0 alpha:1.0]];
productSubLbl.lineBreakMode = UILineBreakModeWordWrap;
productSubLbl.numberOfLines = 3;
[productSubLbl setFont:[UIFont fontWithName:#"Arial" size:10]];
[cell addSubview:productSubLbl];
[productSubLbl release];
NSMutableString *url = [[NSMutableString alloc] initWithString:#""];
NSString *baseImageURL = #"http://samplesite.com/";
NSString *imagePath = [NSString stringWithString:[[[[DataCollection sharedObject] popularProducts]objectAtIndex:indexPath.row] productImage]];
[url appendString:baseImageURL];
[url appendString:imagePath];
NSURL *imageURL = [NSURL URLWithString:url];
NSData *data = [NSData dataWithContentsOfURL:imageURL];
UIImage *img = [[UIImage alloc] initWithData:data cache:NO];
UIImageView *imageView = [[UIImageView alloc] initWithImage:img];
[imageView setFrame:CGRectMake(10, 10, 70, 70)];
[cell addSubview:imageView];
[imageView release];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Pass the url or product id to the detail view. Inside the viewDidLoad of the ProductDetail, create a background thread to retrieve your data. When you background thread finish, it will notify your ProductDetail controller with the detail. At that time, you update your ProductDetailView.
To get your data on a background thread you can use
NSThread
NSOperation
Pass the row into your ProductDetailViewController, and do the fetch in it's viewDidLoad method. You might also want to show a spinner (UIActivityIndicator), and you definitely should read up on background threads.
To make view available to user and loading data after some time you can use NSTimer.
Just have a NSTimer method which will be called in viewDidLoad method as
[NSTimer scheduledTimerWithTimeInterval:<#(NSTimeInterval)ti#> target:<#(id)aTarget#> selector:<#(SEL)aSelector#> userInfo:<#(id)userInfo#> repeats:<#(BOOL)yesOrNo#>]
put some time interval which will be calling your loading method after that.
Hope this helps.