I have the following code to fetch the data from URL, store it in arrays, and display it inside the table.
I had some issue related to fetching and that is solved on SO Click here
Now the issue is data is displayed in the table in a manner which is not the ideal one.
When I run the below code, I get this output. That shaded grey portion is my main concern.
When I try to insert any element say button in that grey shaded area through design view, it gets overlapped by table.
If I change
aTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame] style:UITableViewStyleGrouped];
with
aTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame] style:UITableViewStylePlained];
I get the table output without the grey shadow but it's way too simple.
Note that I'm creating table programmatically.
fetchdataViewController.h
#import <UIKit/UIKit.h>
#interface fetchdataViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
IBOutlet UIWebView *webView;
NSMutableArray *arr1;
NSMutableArray *atarr;
NSMutableArray *arr2;
NSMutableArray *a;
NSMutableArray *b;
NSMutableArray *c;
NSMutableArray *d;
UITableView *aTableView;
}
-(IBAction)btnClicked:(id)sender;
-(IBAction)btnClicked1:(id)sender;
-(void)gainer;
-(void)looser;
#property(nonatomic,retain)NSMutableArray *arr1;
#property(nonatomic,retain)NSMutableArray *arr2;
#property(nonatomic,retain)NSMutableArray *atarr;
#property(nonatomic,retain)NSMutableArray *a;
#property(nonatomic,retain)NSMutableArray *b;
#property(nonatomic,retain)NSMutableArray *c;
#property(nonatomic,retain)NSMutableArray *d;
#property(nonatomic,retain)UIWebView *webView;
#property(nonatomic,retain)UITableView *aTableView;
#end
fetchdataViewController.m
#import "fetchdataViewController.h"
#implementation fetchdataViewController
NSMutableArray *atarr;
NSMutableArray *arr1;
NSMutableArray *arr2;
NSMutableArray *a;
NSMutableArray *b;
NSMutableArray *c;
NSMutableArray *d;
NSMutableString *mainstr;
NSMutableString *str;
#synthesize webView;
#synthesize arr1;
#synthesize arr2;
#synthesize atarr;
#synthesize a;
#synthesize b;
#synthesize c;
#synthesize d;
#synthesize aTableView;
int i,j;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [a count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier=#"Cell";
static NSInteger StateTag = 1;
static NSInteger CapitalTag = 2;
static NSInteger StateTag1 = 3;
static NSInteger StateTag2 = 4;
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell=[[[UITableViewCell alloc]initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]autorelease];
CGRect frame;
frame.origin.x = 10;
frame.origin.y = 5;
frame.size.height = 35;
frame.size.width = 170;
UILabel *capitalLabel = [[UILabel alloc] initWithFrame:frame];
capitalLabel.tag = CapitalTag;
[cell.contentView addSubview:capitalLabel];
frame.origin.x += 125;
UILabel *stateLabel = [[UILabel alloc] initWithFrame:frame];
stateLabel.tag = StateTag;
[cell.contentView addSubview:stateLabel];
frame.origin.x += 100;
UILabel *stateLabel1 = [[UILabel alloc] initWithFrame:frame];
stateLabel1.tag = StateTag1;
[cell.contentView addSubview:stateLabel1];
frame.origin.x += 100;
UILabel *stateLabel2 = [[UILabel alloc] initWithFrame:frame];
stateLabel2.tag = StateTag2;
[cell.contentView addSubview:stateLabel2];
}
UILabel *capitalLabel = (UILabel *) [cell.contentView viewWithTag:CapitalTag];
UILabel *stateLabel = (UILabel *) [cell.contentView viewWithTag:StateTag];
UILabel *stateLabel1 = (UILabel *) [cell.contentView viewWithTag:StateTag1];
UILabel *stateLabel2 = (UILabel *) [cell.contentView viewWithTag:StateTag2];
capitalLabel.text=[a objectAtIndex:indexPath.row];
stateLabel.text = [b objectAtIndex:indexPath.row];
stateLabel1.text = [c objectAtIndex:indexPath.row];
stateLabel2.text = [d objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)btnClicked:(id)sender{
[self gainer];
}
-(IBAction)btnClicked1:(id)sender {
[self looser];
}
-(void)gainer{
arr1=[[NSMutableArray alloc]init];
arr2=[[NSMutableArray alloc]init];
a=[[NSMutableArray alloc]init];
b=[[NSMutableArray alloc]init];
c=[[NSMutableArray alloc]init];
d=[[NSMutableArray alloc]init];
NSURL *url=[NSURL URLWithString:#"http://ipad.idealake.com/default.aspx?id=G"];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
[webView loadRequest:req];
//storing page data in string
mainstr=[[NSMutableString alloc] initWithContentsOfURL:url];
atarr=[mainstr componentsSeparatedByString:#"#"];
NSString *str2;
NSString *str3;
for(int i=0; i<[atarr count]-1; i++)
{
// NSLog(#"i=:%i",i);
NSMutableString *str = [atarr objectAtIndex:i];
if (str!= nil)
arr1=[str componentsSeparatedByString:#";"];
for (int k=0;k<[arr1 count];k++)
{
str2 = [arr1 objectAtIndex:k];
[arr2 addObject:str2];
}
}
else
{
//NSLog (#"Nill");
}
}
for(int l=0;l<[arr2 count]/4;l++){
str3=[arr2 objectAtIndex:4*l];
[a addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+1];
[b addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+2];
[c addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+3];
[d addObject:str3];
}
}
-(void)looser{
arr1=[[NSMutableArray alloc]init];
arr2=[[NSMutableArray alloc]init];
a=[[NSMutableArray alloc]init];
b=[[NSMutableArray alloc]init];
c=[[NSMutableArray alloc]init];
d=[[NSMutableArray alloc]init];
NSURL *url=[NSURL URLWithString:#"http://ipad.idealake.com/default.aspx?id=L"];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
[webView loadRequest:req];
mainstr=[[NSMutableString alloc] initWithContentsOfURL:url];
atarr=[mainstr componentsSeparatedByString:#"#"];
NSString *str2;
NSString *str3;
for(int i=0; i<[atarr count]-1; i++)
{
NSMutableString *str = [atarr objectAtIndex:i];
if (str!= nil)
{
arr1=[str componentsSeparatedByString:#";"];
for (int k=0;k<[arr1 count];k++)
{
str2 = [arr1 objectAtIndex:k];
[arr2 addObject:str2];
}
}
else
{
//NSLog (#"Nill");
}
}
for(int l=0;l<[arr2 count]/4;l++){
str3=[arr2 objectAtIndex:4*l];
[a addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+1];
[b addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+2];
[c addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+3];
[d addObject:str3];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
arr1=[[NSMutableArray alloc]init];
arr2=[[NSMutableArray alloc]init];
a=[[NSMutableArray alloc]init];
b=[[NSMutableArray alloc]init];
c=[[NSMutableArray alloc]init];
d=[[NSMutableArray alloc]init];
[self gainer];
[super viewDidLoad];
aTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame] style:UITableViewStyleGrouped];
aTableView.dataSource = self;
aTableView.delegate = self;
aTableView.frame = CGRectMake(0, 10, 720, 500);
[self.view addSubview:aTableView];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
THANKS IN ADVANCE
If your problem is to remove the lightgrey area from your groupedtableview, then you can remove the shaded grey area by adding this to your code:
if ([myTable respondsToSelector:#selector(backgroundView)]) {
myTable.backgroundView = nil;
}
It's an issue that only iPad has with groupedTableViewStyle.
At first of all why you are writing this line two times?? [super viewDidLoad]; in tableview
Secondly i think you are displaying your fetch data into an webview which is into the table view.i do not understanding that if you are making your table pro grammatically then how could you display webview using IBOutlet into the tablevie?!!
I think you can try this[webView setOpaque:NO]; May be it will solve the problem..
Related
I'am dealing with a problem the past few days. I have a UIScrollView in a xib file, in this UIScrollView i put UIViews (as xib too), and in them UIViews i put UITableViews (as xib too). But as a rookie i always populated my UITableView using cellForRowAtindexPath, you return the cell with your wanted text and it's all done, but this time it is not called, so maybe there is another way to populate it ?. As information i'am trying to use CollapseClick as my view. If someone could help me please or have the slightest idea about how to populate it feel free to answer please.
here is my code, i spare you all the xml parsing process.
.m were i init my UITableView
- (void)viewDidLoad
{
[super viewDidLoad];
newsTable = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] bounds] style:UITableViewCellStyleDefault];
newsTable.delegate = self;
//newsTable.dataSource = self;
myCollapseClick.CollapseClickDelegate = self;
[myCollapseClick reloadCollapseClick];
// If you want a cell open on load, run this method:
[myCollapseClick openCollapseClickCellAtIndex:0 animated:YES];
/*
// If you'd like multiple cells open on load, create an NSArray of NSNumbers
// with each NSNumber corresponding to the index you'd like to open.
// - This will open Cells at indexes 0,2 automatically
NSArray *indexArray = #[[NSNumber numberWithInt:0],[NSNumber numberWithInt:2]];
[myCollapseClick openCollapseClickCellsWithIndexes:indexArray animated:NO];
*/
}
were i need to return the UIViews with the UITable views
-(UIView *)viewForCollapseClickContentViewAtIndex:(int)index {
switch (index) {
case 0:
return test1View;
break;
case 1:
return test2View;
break;
case 2:
return test3View;
break;
default:
return test1View;
break;
}
}
the good old cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
CGRect frame = CGRectMake(0, 0, 300, 50);
UILabel *lbl1 = [[UILabel alloc] initWithFrame:frame];
lbl1.textAlignment = NSTextAlignmentCenter;
[lbl1 setFont:[UIFont fontWithName:#"Helvetica" size:12.0]];
//self.tableView.separatorColor = [UIColor whiteColor];
//lbl1.backgroundColor = [UIColor purpleColor];
[lbl1 setTextColor:[UIColor blackColor]];
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
if (storyIndex == 0 && FlagS)
{
NSMutableArray * SIR = [[NSUserDefaults standardUserDefaults] objectForKey:#"sizingSheet"];
NSString * SID = [[SIR objectAtIndex: storyIndex] objectForKey: #"sizing_id"];
NSString *DID = [[SIR objectAtIndex: storyIndex] objectForKey: #"data_id"];
Request = [[restRequestManager alloc]init];
NSString *SDD = [NSString stringWithFormat:#"%#%#%#%#%#", #"sizing_id=", SID, #"&", #"data_id=", DID];
NSData* Mimage = [Request restTestRequesterImage:#"http://www.stackoverflow.com" serviceUri:#"question/Post" parameters:SDD technique:#"POST"];
cell.imageView.image = [UIImage imageWithData:Mimage];
return cell;
}
searchString = #"TH_MEASURE_CATEGORY_";
str=[category objectAtIndex:storyIndex];
NSArray *array = [[NSMutableArray alloc]init];
array = [str componentsSeparatedByString:#"#"];
for (NSString *tempStr in array) {
NSComparisonResult result = [tempStr compare:searchString options:(NSCaseInsensitiveSearch) range:NSMakeRange(0, [searchString length])];
if (result == NSOrderedSame) {
lbl1.text = [category objectAtIndex: storyIndex];
lbl1.text = [lbl1.text substringFromIndex: MIN(20, [lbl1.text length])];
[cell.contentView addSubview:lbl1];
}
else{
lbl1.text = [category objectAtIndex: storyIndex];
[cell.contentView addSubview:lbl1];
}
}
return cell;
}
and the .h without all the useless stuff
#interface MeasuresViewController: UIViewController <CollapseClickDelegate,UITextFieldDelegate, UITableViewDelegate, UITableViewDelegate> {
IBOutlet UIView *test1View;
IBOutlet UIView *test2View;
IBOutlet UIView *test3View;
__weak IBOutlet CollapseClick *myCollapseClick;
IBOutlet UITableView * newsTable;
BOOL *FlagS;
UIActivityIndicatorView * activityIndicator;
CGSize cellSize;
NSMutableArray * stories;
NSMutableString * currentCategory, * currentSubcategory, * currentValue, * currentName, * currentSrc;
NSDictionary *data, *data1, *data2, *data3, *data4;
}
- (void)parseXMLFileAtURL:(NSString *)URL;
-(BOOL)ifStringExists:(NSString *)stringSentToCheck selectYourCheckArray:(NSMutableArray *)SelectedArray;
#property (nonatomic, strong) NSMutableArray *photos;
#property (atomic, strong) NSMutableArray *assets;
#end
You commented out the line that sets the data source. If a data source is not set then cellForRowAtIndexPath: will not be called.
Your current viewDidLoad code is:
- (void)viewDidLoad {
[super viewDidLoad];
newsTable = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] bounds] style:UITableViewCellStyleDefault];
newsTable.delegate = self;
//newsTable.dataSource = self;
myCollapseClick.CollapseClickDelegate = self;
[myCollapseClick reloadCollapseClick];
// If you want a cell open on load, run this method:
[myCollapseClick openCollapseClickCellAtIndex:0 animated:YES];
/*
// If you'd like multiple cells open on load, create an NSArray of NSNumbers
// with each NSNumber corresponding to the index you'd like to open.
// - This will open Cells at indexes 0,2 automatically
NSArray *indexArray = #[[NSNumber numberWithInt:0],[NSNumber numberWithInt:2]];
[myCollapseClick openCollapseClickCellsWithIndexes:indexArray animated:NO];
*/
}
Change it to
- (void)viewDidLoad
{
[super viewDidLoad];
newsTable = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] bounds] style:UITableViewCellStyleDefault];
newsTable.delegate = self;
newsTable.dataSource = self;
myCollapseClick.CollapseClickDelegate = self;
[myCollapseClick reloadCollapseClick];
// If you want a cell open on load, run this method:
[myCollapseClick openCollapseClickCellAtIndex:0 animated:YES];
/*
// If you'd like multiple cells open on load, create an NSArray of NSNumbers
// with each NSNumber corresponding to the index you'd like to open.
// - This will open Cells at indexes 0,2 automatically
NSArray *indexArray = #[[NSNumber numberWithInt:0],[NSNumber numberWithInt:2]];
[myCollapseClick openCollapseClickCellsWithIndexes:indexArray animated:NO];
*/
}
I am using asyncimageview classes nicely provided by: http://www.markj.net/iphone-asynchronous-table-image/
I am getting image urls from a json file and loading each image to a cell.
Problem:
When i scroll up, and scroll back down to the same cell, the image reloads (disappears and appears again). I can't figure out why the image keeps reloading? Does anyone have suggestions or a solution to how I could make it stop? Thanks in advance!
// Asks the data source to return a cell to insert in a particular table view location
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Gets the current news article
NewsArticle *theCurrentArticle = [self.listofNewsArticles objectAtIndex:[indexPath row]];
//Gets the title from the current article
NSString *theTitle = theCurrentArticle.title;
//Gets the image url
NSString *imageUrl = theCurrentArticle.imageURL;
//Gets the description of the current news article
NSString *theDescription = theCurrentArticle.description;
NewsCustomCell *cell = (NewsCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"NewsContent"];
__block NewsCustomCell *aCell;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (cell == nil) {
aCell = (NewsCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"NewsContent"];
} else {
AsyncImageView* oldImage = (AsyncImageView*)
[cell.contentView viewWithTag:999];
[oldImage removeFromSuperview];
}
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(5, 5, 100, 100)];
imageView.tag = 999;
dispatch_async(dispatch_get_main_queue(), ^{
[imageView loadImageFromURL:[NSURL URLWithString:imageUrl]];
[cell.contentView addSubview:imageView];
cell.titleLabel.text = theTitle;
cell.descriptionLabel.text = theDescription;
cell.imageLabel.contentMode = UIViewContentModeScaleAspectFill;
});
});
return cell;
}
Heres what the current app looks like:
Solution:
Just worked with this class I finally found.
https://github.com/rs/SDWebImage
This handles caching, async downloads. Wish I found this sooner..
I hope you have Write AsyncImageView and ImageCache and ImageCacheObject classes.
Write this code inside cellForRowAtIndexPath:
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Quest_Forum *Quest_ForumObj=[queArr objectAtIndex:i+indexPath.row];
// NSLog(#"cell for row at... i val.. %d",i+indexPath.row);
for(UIView * view in cell.contentView.subviews){
if([view isKindOfClass:[AsyncImageView class]])
{
// NSLog(#"remove old images");
[view removeFromSuperview];
view = nil;
}
}
AsyncImageView *asyncImageView = nil;
UIImageView *cellImage = (UIImageView *)[cell viewWithTag:1]; // Inside tableview i have taken tableviewcell and given tag 1 to that imageview
asyncImageView = [[AsyncImageView alloc] initWithFrame:cellImage.frame] ;
[asyncImageView loadImageFromURL:Quest_ForumObj.Quest_Image];
asyncImageView.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:asyncImageView];
UILabel *lblQuest = (UILabel *)[cell viewWithTag:2]; // Given tag 2 to the label inside tableViewCell
lblQuest.text=Quest_ForumObj.Question;
In ImageCacheObject.h
#class ImageCacheObject;
#interface ImageCache : NSObject
{
NSUInteger totalSize; // total number of bytes
NSUInteger maxSize; // maximum capacity
NSMutableDictionary *myDictionary;
}
#property (nonatomic, readonly) NSUInteger totalSize;
-(id)initWithMaxSize:(NSUInteger) max;
-(void)insertImage:(UIImage*)image withSize:(NSUInteger)sz forKey:(NSString*)key;
-(UIImage*)imageForKey:(NSString*)key;
In ImageCacheObject.m
#import "ImageCacheObject.h"
#synthesize totalSize;
-(id)initWithMaxSize:(NSUInteger) max
{
if (self = [super init])
{
totalSize = 0;
maxSize = max;
myDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
-(void)dealloc // Don't write this method if you are using ARC
{
[myDictionary release];
[super dealloc];
}
-(void)insertImage:(UIImage*)image withSize:(NSUInteger)sz forKey:(NSString*)key
{
// NSLog(#"count of insert image%d",sz);
ImageCacheObject *object = [[ImageCacheObject alloc] initWithSize:sz Image:image];
while (totalSize + sz > maxSize)
{
NSDate *oldestTime;
NSString *oldestKey;
for (NSString *key in [myDictionary allKeys])
{
ImageCacheObject *obj = [myDictionary objectForKey:key];
if (oldestTime == nil || [obj.timeStamp compare:oldestTime] == NSOrderedAscending)
{
oldestTime = obj.timeStamp;
oldestKey = key;
}
}
if (oldestKey == nil)
break; // shoudn't happen
ImageCacheObject *obj = [myDictionary objectForKey:oldestKey];
totalSize -= obj.size;
[myDictionary removeObjectForKey:oldestKey];
}
[myDictionary setObject:object forKey:key];
[object release];
}
-(UIImage*)imageForKey:(NSString*)key
{
ImageCacheObject *object = [myDictionary objectForKey:key];
if (object == nil)
return nil;
[object resetTimeStamp];
return object.image;
}
In ImageCacheObject.h
#interface ImageCacheObject : NSObject
{
NSUInteger size; // size in bytes of image data
NSDate *timeStamp; // time of last access
UIImage *image; // cached image
}
#property (nonatomic, readonly) NSUInteger size;
#property (nonatomic, retain, readonly) NSDate *timeStamp;
#property (nonatomic, retain, readonly) UIImage *image;
-(id)initWithSize:(NSUInteger)sz Image:(UIImage*)anImage;
-(void)resetTimeStamp;
In ImageCacheObject.m
#synthesize size;
#synthesize timeStamp;
#synthesize image;
-(id)initWithSize:(NSUInteger)sz Image:(UIImage*)anImage
{
if (self = [super init])
{
size = sz;
timeStamp = [[NSDate date] retain];
image = [anImage retain];
}
return self;
}
-(void)resetTimeStamp
{
[timeStamp release];
timeStamp = [[NSDate date] retain];
}
-(void) dealloc
{
[timeStamp release];
[image release];
[super dealloc];
}
This is my code to show the table view inside alert view. Its working perfectly in iOS 5.1. But in iOS 6.0 it doesnt show the table view inside alert view.
UIAlertTableView.h
#import <UIKit/UIKit.h>
#class UIAlertView;
#interface UIAlertTableView : UIAlertView {
// The Alert View to decorate
UIAlertView *alertView;
// The Table View to display
UITableView *tableView;
// Height of the table
int tableHeight;
// Space the Table requires (incl. padding)
int tableExtHeight;
id<UITableViewDataSource> dataSource;
id<UITableViewDelegate> tableDelegate;
NSArray *names;
NSArray *prices;
NSString *priceText;
NSInteger rowsCount;
NSInteger total;
}
#property (nonatomic, assign) id dataSource;
#property (nonatomic, assign) id tableDelegate;
#property (nonatomic, readonly) UITableView *tableView;
#property (nonatomic, assign) int tableHeight;
#property (nonatomic, assign) NSInteger total;
- (void)prepare;
#end
UIAlertTableView.m
#import "UIAlertTableView.h"
#define kTablePadding 8.0f
#interface UIAlertView (private)
- (void)layoutAnimated:(BOOL)fp8;
#end
#implementation UIAlertTableView
#synthesize dataSource;
#synthesize tableDelegate;
#synthesize tableHeight;
#synthesize tableView;
#synthesize total;
- (void)layoutAnimated:(BOOL)fp8 {
[super layoutAnimated:fp8];
[self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y - tableExtHeight/2, self.frame.size.width, self.frame.size.height + tableExtHeight)];
// We get the lowest non-control view (i.e. Labels) so we can place the table view just below
UIView *lowestView;
int i = 0;
while (![[self.subviews objectAtIndex:i] isKindOfClass:[UIControl class]]) {
lowestView = [self.subviews objectAtIndex:i];
i++;
}
CGFloat tableWidth = 262.0f;
tableView.frame = CGRectMake(11.0f, lowestView.frame.origin.y + lowestView.frame.size.height + 2 * kTablePadding, tableWidth, tableHeight);
for (UIView *sv in self.subviews) {
// Move all Controls down
if ([sv isKindOfClass:[UIControl class]]) {
sv.frame = CGRectMake(sv.frame.origin.x, sv.frame.origin.y + tableExtHeight, sv.frame.size.width, sv.frame.size.height);
}
}
}
- (void)show{
self.total = 0;
[self prepare];
[super show];
}
- (NSInteger)tableView:(UITableView *)alerttableView numberOfRowsInSection:(NSInteger)section
{
/*
code to show some app data in rows
// NSMutableDictionary *rowsUponDict = [AppDelegate productsPFObjectDictionaryAppDelegate];
NSMutableArray *productsNames = [AppDelegate productsPFObjectDictionaryNamesAppDelegate];
// rowsCount = [[rowsUponDict allKeys] count];
rowsCount = [productsNames count];
NSLog(#"rowsUponDict count: %d",rowsCount);
return rowsCount+1;
*/
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)alerttableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LazyTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
/*
code to show some app data in rows
if (indexPath.row == rowsCount) {
cell.textLabel.text = #"Total Amount:";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d",self.total];
}
else {
cell.textLabel.text = [names objectAtIndex:indexPath.row];
priceText = [NSString stringWithFormat:#"%#", [prices objectAtIndex:indexPath.row]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Rs.%#",priceText];
}
*/
return cell;
}
- (void)prepare {
if (tableHeight == 0) {
tableHeight = 250.0f;
}
/*
calculation os some app data
NSInteger priceInt;
names = [[NSArray alloc] initWithArray:[AppDelegate productsPFObjectDictionaryNamesAppDelegate]];
NSLog(#"Names: %#",names);
prices = [[NSArray alloc] initWithArray:[AppDelegate productsPFObjectDictionaryPricesAppDelegate]];
NSLog(#"prices: %#",prices);
for (int i=0; i<[prices count]; i++) {
priceText = [NSString stringWithFormat:#"%#", [prices objectAtIndex:i]];
priceInt = [priceText integerValue];
self.total = self.total + priceInt;
NSLog(#"tatal: %d",self.total);
}
*/
tableExtHeight = tableHeight + 2 * kTablePadding;
tableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f) style:UITableViewStylePlain];
tableView.delegate = tableDelegate;
tableView.dataSource = dataSource;
[self addSubview:tableView];
// [self insertSubview:tableView atIndex:0];
[self setNeedsLayout];
}
- (void)dealloc {
[tableView release];
[super dealloc];
}
#end
This is how I use it
UIAlertTableView *popUpCartItems = [[UIAlertTableView alloc] initWithTitle:#"Cart" message:nil delegate:self cancelButtonTitle:#"Close" otherButtonTitles:#"CheckOut",nil];
popUpCartItems.tableDelegate = popUpCartItems;
popUpCartItems.dataSource = popUpCartItems;
popUpCartItems.tableHeight = 132;
[popUpCartItems show];
Any help is greatly appreciated
Check the following link
https://github.com/simonb/SBTableAlert
I tested on both iOS 5.0 and iOS 6.0 and its work perfectly for me.
You just need to do download that code and use in your project.
Hope this will help you !!!
Try setting a frame for your tableview before adding it to UIAlertView. May be as follows.
tableView.frame = CGRectMake(0, 0, 280, 100);
[self addSubview:tableView];
I'm trying to load a table with content from Twitter. The table is in a UIView and being created in the drawRect()...but I keep getting a warning:
Property access result unused - getters should not be used for side effects
on each.
Nothing show up in my table.
Here's my .h file:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <Twitter/Twitter.h>
#import "ColorController.h"
#interface TwitterController : UIView <UITableViewDelegate, UITableViewDataSource> {
UIButton* btnCloseView;
UITableView* tblTweets;
UIImageView* imgTwitterIcon;
ColorController* colorManager;
NSMutableArray* tweetsArray;
NSString* twitterID;
}
#property (nonatomic, retain) NSString* twitterID;
- (void) getTweets;
- (void) closeWin;
#end
and my .m
#import "TwitterController.h"
#implementation TwitterController
#synthesize twitterID;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
colorManager = [ColorController new];
}
return self;
}
- (void)drawRect:(CGRect)rect {
imgTwitterIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"imgTwitterBird"]];
CGRect twitterIconFrame = [imgTwitterIcon frame];
twitterIconFrame.origin.x = 50.0;
twitterIconFrame.origin.y = 20.0;
tblTweets = [[UITableView alloc] initWithFrame:CGRectMake(50.0, 25.0, 220.0, 500.0)];
tblTweets.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tblTweets.separatorColor = [colorManager setColor:176.0:196.0:222.0];
tblTweets.layer.borderWidth = 1.0;
tblTweets.rowHeight = 20.0;
tblTweets.scrollEnabled = YES;
tblTweets.delegate.self;
tblTweets.dataSource.self;
UIImage* imgCloseButton = [UIImage imageNamed:#"btnCloseWindow.png"];
CGSize imageSize = imgCloseButton.size;
btnCloseView = [[UIButton alloc] initWithFrame: CGRectMake(220.0, 550.0, imageSize.width, imageSize.height)];
[btnCloseView setImage:[UIImage imageNamed:#"btnCloseWindow.png"] forState:UIControlStateNormal];
[btnCloseView addTarget:self action:#selector(closeWin:) forControlEvents:UIControlEventTouchUpInside];
[self getTweets];
[self addSubview:tblTweets];
[self addSubview:imgTwitterIcon];
[self addSubview:btnCloseView];
}
- (void) getTweets {
//array to hold tweets
tweetsArray = [[NSMutableArray alloc] init];
///set up a NSURL to the twitter API
NSURL* twitterAPI = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=%#&count=10", twitterID]];
//get last 10 tweets (max is 20)
TWRequest *twitterRequest = [[TWRequest alloc] initWithURL:twitterAPI
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *tweetsDict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
for(NSDictionary* thisTweetDict in tweetsDict) {
[tweetsArray addObject:[thisTweetDict objectForKey:#"text"]];
}
[tblTweets reloadData];
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
#pragma mark Table Management
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tweetsArray count];
NSLog(#"%i", [tweetsArray count]);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tweetsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.textColor = [UIColor colorWithRed:66.0/255.0 green:66.0/255.0 blue:66.0/255.0 alpha:1];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size: 13.0];
cell.textLabel.text = [tweetsArray objectAtIndex:indexPath.row];
CGRect cellFrame = [cell frame];
cellFrame.size.height = 25.0;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* thisTweet = [tweetsArray objectAtIndex:indexPath.row];
}
#pragma mark Close Window
- (void) closeWin {
NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];
[userData setObject:#"closeTwitter" forKey:#"theEvent"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"theMessenger" object:self userInfo: userData];
}
#end
drawRect is used to draw stuff inside this views, using drawing functions
You should move your views additions to the layoutSubviews
Instead of - (void)drawRect:(CGRect)rect use - (void)layoutSubviews
This may or may not solve your issues, but nevertheless its the correct approach
My app is want to get the albums list of the iphone and all the photos in certain album.
In the app I enumerate the photos in one album of the iphone.
As there may be lots of photos of certain album, considering of performance I use GCD:dispatch_async. But it always crashes when the tableview cell updates which is invoked by KVO.
I've no idea about whether I use KVO or GCD in a wrong way.
Now alternatively I use performSelectorInBackground: replacing of dispatch_async. Now the app is not crashed but the app's performance is poor: the title of the cell will only be shown when you touch on it or scroll the tableview when there are many photos. In other words, the main thread must be blocked.
Attached is the code and the core code is in AlbumListViewController.m.
Can any one help me to check it ?
I just want to know:
1 why the app is crashed if using dispatch_async
2 how can I improve the performance in case of many photos.
thanks.
Below is my Code:
//
// RootViewController.h
// AlbumDemo
#import
#interface RootViewController : UITableViewController {
NSMutableArray *_listArray;
}
#property (nonatomic, retain) NSMutableArray *listArray;
#end
// RootViewController.m
#import "RootViewController.h"
#import
#import "AlbumListViewController.h"
NSString *thumnail = #"thumnail";
NSString *albumName = #"albumName";
NSString *albumNum = #"albumNum";
NSString *albumGroup = #"albumGroup";
#implementation RootViewController
#synthesize listArray = _listArray;
#pragma -
#pragma Function
- (void)setUp
{
_listArray = [[NSMutableArray alloc] initWithCapacity:1];
self.title = #"Albums";
}
- (void)fetchAlbumList
{
ALAssetsLibrary *assetLib = [[[ALAssetsLibrary alloc] init] autorelease];
ALAssetsFilter *fileter = [ALAssetsFilter allPhotos];
[assetLib enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if (group)
{
[group setAssetsFilter:fileter];
NSString *_groupName = [group valueForProperty:ALAssetsGroupPropertyName];
NSNumber *_groupNum = [NSNumber numberWithInteger:[group numberOfAssets]];
UIImage *_groupImage = [UIImage imageWithCGImage:[group posterImage]];
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:_groupName,albumName,_groupNum,albumNum,_groupImage,thumnail,group,albumGroup, nil];
[_listArray addObject:dic];
[self.tableView reloadData];
}
else
{
NSLog(#"_listArray :%#",_listArray);
}
}
failureBlock:^(NSError *error)
{
NSLog(#"Error: %#", error);;
}
];
}
#pragma -
#pragma ViewController lift cycle
- (void)viewDidLoad
{
[super viewDidLoad];
[self setUp];
[self fetchAlbumList];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_listArray count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UILabel *nameLab = nil;
UILabel *numLab = nil;
UIImageView *thumnailImage = nil;
UIFont *font = [UIFont boldSystemFontOfSize:18];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
thumnailImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0,50, 50)];
thumnailImage.tag = 100;
[cell.contentView addSubview:thumnailImage];
[thumnailImage release];
nameLab = [[UILabel alloc] initWithFrame:CGRectMake(60, 10, 100, 30)];
nameLab.tag = 200;
nameLab.backgroundColor = [UIColor clearColor];
nameLab.font = font;
[cell.contentView addSubview:nameLab];
[nameLab release];
numLab = [[UILabel alloc] initWithFrame:CGRectMake(200, 10, 50, 30)];
numLab.tag = 300;
numLab.backgroundColor = [UIColor clearColor];
numLab.textColor = [UIColor grayColor];
numLab.font = font;
[cell.contentView addSubview:numLab];
[numLab release];
}
else
{
thumnailImage = (UIImageView *)[cell.contentView viewWithTag:100];
nameLab = (UILabel *)[cell.contentView viewWithTag:200];
numLab = (UILabel *)[cell.contentView viewWithTag:300];
}
NSDictionary *dic = [self.listArray objectAtIndex:indexPath.row];
thumnailImage.image = (UIImage *)[dic valueForKey:thumnail];
NSString *title = [dic valueForKey:albumName];
CGSize titleSize = [title sizeWithFont:font];
CGRect rect = nameLab.frame;
rect.size = titleSize;
nameLab.frame = rect;
nameLab.text = title;
rect = numLab.frame;
rect.origin.x = 60 + nameLab.frame.size.width + 10;
numLab.frame = rect;
numLab.text = [NSString stringWithFormat:#"(%d)",[[dic valueForKey:albumNum] intValue]];
// Configure the cell.
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dic = [self.listArray objectAtIndex:indexPath.row];
AlbumListViewController *viewController = [[AlbumListViewController alloc] initWithAssetGroup:[dic valueForKey:albumGroup]];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc
{
My_Release (_listArray);
[super dealloc];
}
#end
// AlbumListViewController.h
// AlbumDemo
#import
#import
#interface AlbumListViewController : UITableViewController {
NSMutableArray *_marr;
ALAssetsGroup *_assetsGroup;
}
#property (nonatomic, retain) NSMutableArray *list;
#property (nonatomic, retain) ALAssetsGroup *assetsGroup;
- (id)initWithAssetGroup:(ALAssetsGroup *)group;
#end
// AlbumListViewController.m
// AlbumDemo
#import "AlbumListViewController.h"
#interface PhotoObj : NSObject {
NSString *_name;
UIImage *_thumbnail;
UIImage *_fullImage;
}
#property (nonatomic, copy ) NSString *name;
#property (nonatomic, retain) UIImage *thumbnail;
#property (nonatomic, retain) UIImage *fullImage;
#end
#implementation PhotoObj
#synthesize name = _name;
#synthesize thumbnail = _thumbnail,fullImage = _fullImage;
- (void)dealloc
{
My_Release(_thumbnail);
My_Release(_fullImage);
My_Release(_name);
[super dealloc];
}
#end
#interface AlbumListViewController()
- (NSMutableArray*)list;
- (NSUInteger)countOfList;
- (id)objectInListAtIndex:(NSUInteger)idx;
- (void)insertObject:(id)anObject inListAtIndex:(NSUInteger)idx;
- (id)objectInListAtIndex:(NSUInteger)idx;
- (void)removeObjectFromListAtIndex:(NSUInteger)idx;
- (void)replaceObjectInListAtIndex:(NSUInteger)idx withObject:(id)anObject;
- (void)setList:(NSMutableArray *)_arr;
#end
#implementation AlbumListViewController
#synthesize assetsGroup = _assetsGroup;
- (id)initWithAssetGroup:(ALAssetsGroup *)group
{
self = [self initWithStyle:UITableViewStylePlain];
if (self )
{
_marr = [[NSMutableArray alloc] initWithCapacity:1];
self.assetsGroup = group;
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
return self;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
My_Release(_marr);
My_Release(_assetsGroup);
[self removeObserver:self forKeyPath:#"list"];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)parseAssetGroup
{
[_marr removeAllObjects];
[self.assetsGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result)
{
PhotoObj *obj = [[PhotoObj alloc] init];
obj.thumbnail = [UIImage imageWithCGImage:[result thumbnail]];
ALAssetRepresentation *represention = [result defaultRepresentation];
obj.fullImage = [UIImage imageWithCGImage:[represention fullScreenImage]];
obj.name = [[represention url] absoluteString];
[self willChangeValueForKey:#"list"];
[self insertObject:obj inListAtIndex:[_marr count]];
[self didChangeValueForKey:#"list"];
My_Release(obj);
}
}];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self addObserver:self forKeyPath:#"list" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:NULL];
/*
if performSelectorInBackground, the perofrmance is poor
as the title of the cell will be shown in a long time and it now seems the main thread is blocked
*/
[self performSelectorInBackground:#selector(parseAssetGroup) withObject:nil];
/*
using dispatch_async it always crashes
as it says the sth is wrong with the tableview update
*/
// dispatch_async(dispatch_get_main_queue(), ^{
// [self parseAssetGroup];
// });
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
#pragma mark - Table view data source
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_marr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UIImageView *thumbNail = nil;
UILabel *nameLab = nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
thumbNail = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
thumbNail.tag = 99;
[cell.contentView addSubview:thumbNail];
[thumbNail release];
nameLab = [[UILabel alloc] initWithFrame:CGRectMake(60, 10, 240, 40)];
nameLab.numberOfLines = 2;
nameLab.font = [UIFont systemFontOfSize:16];
nameLab.tag = 199;
[cell.contentView addSubview:nameLab];
[nameLab release];
}
else
{
thumbNail = (UIImageView *)[cell.contentView viewWithTag:99];
nameLab = (UILabel *)[cell.contentView viewWithTag:199];
}
// Configure the cell...
PhotoObj *obj = [_marr objectAtIndex:indexPath.row];
nameLab.text = obj.name;
thumbNail.image = obj.thumbnail;
return cell;
}
#pragma mark -
- (NSUInteger)countOfList
{
return [_marr count];
}
- (NSMutableArray*)list
{
return _marr;
}
- (void)setList:(NSMutableArray *)_arr
{
if (_marr != _arr)
{
[_marr release];
_marr = _arr;
}
}
- (id)objectInListAtIndex:(NSUInteger)idx
{
return [_marr objectAtIndex:idx];
}
- (void)insertObject:(id)anObject inListAtIndex:(NSUInteger)idx
{
if ([NSThread isMainThread])
{
NSLog(#"insert main thread");
}
else
{
NSLog(#"insert not main thread");
}
[_marr insertObject:anObject atIndex:idx];
}
- (void)removeObjectFromListAtIndex:(NSUInteger)idx
{
[_marr removeObjectAtIndex:idx];
}
- (void)replaceObjectInListAtIndex:(NSUInteger)idx withObject:(id)anObject
{
[_marr replaceObjectAtIndex:idx withObject:anObject];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSIndexSet *indices = [change objectForKey:NSKeyValueChangeIndexesKey];
if (indices == nil)
return; // Nothing to do
// Build index paths from index sets
NSUInteger indexCount = [indices count];
NSUInteger buffer[indexCount];
[indices getIndexes:buffer maxCount:indexCount inIndexRange:nil];
NSMutableArray *indexPathArray = [NSMutableArray array];
for (int i = 0; i
I ran into exactly the same problem today. In short, the reason is you cannot do UIKit related tasks, like updating a table, or in my case a Textview, from the background dispatch queue. Check the link below for more details.
comparison GCD vs. performSelectorInBackground: dispatch_async not in background
A possible solution is the following: instead of assigning your fresh data in your update block directly to the KVO variable which causes the crash, you dispatch another block which does this to the main queue, from inside your update block. If you use the dispatch_async_f function to do this, you can pass a pointer to your data as context.
Like this:
dispatch_async(yourQueue, ^() {
NSArray *data;
// do stuff to alloc and fill the array
// ...
dispatch_async(dispatch_get_main_queue(), ^() {
myObj.data = data; // the assignment, which triggers the KVO.
});
});
For me this works without retaining and releasing the data. Not sure, if this correct.