how to play videos in Landscape mode in iphone - ios

any one help me i am not using MPMoviePlayerController jest i am tack in UItableView in Four cells
#import "VSChannelListViewController.h"
#import "VSPlayerViewController.h"
#interface Channel : NSObject {
NSString *_name;
NSString *_urlAddress;
NSString *_description;
NSDictionary *_options;
}
#property (nonatomic, readonly) NSString *name;
#property (nonatomic, readonly) NSString *urlAddress;
#property (nonatomic, readonly) NSString *description;
#property (nonatomic, readonly) NSDictionary *options;
+ (id)channelWithName:(NSString *)name addr:(NSString *)addr description:(NSString *)description options:(NSDictionary *)options;
- (id)initWithName:(NSString *)name addr:(NSString *)addr description:(NSString *)description options:(NSDictionary *)options;
#end
#implementation Channel
#synthesize name = _name;
#synthesize urlAddress = _urlAddress;
#synthesize description = _description;
#synthesize options = _options;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.title = #"Channel List";
_channelList = [[NSMutableArray array] retain];
Channel *c1 = [Channel channelWithName:#"TEST" addr:#"rtsp://202.65.154.103:1935/live/text.stream" description:#"justin reporter" options:[NSDictionary dictionaryWithObject:VSDECODER_OPT_VALUE_RTSP_TRANSPORT_TCP forKey:VSDECODER_OPT_KEY_RTSP_TRANSPORT]];
[_channelList addObject:c1];
Channel *c2 = [Channel channelWithName:#"Cartoon TV" addr:#"rtsp://ws2.gpom.com/cartoon" description:#"justin reporter Pavan" options:[NSDictionary dictionaryWithObject:VSDECODER_OPT_VALUE_RTSP_TRANSPORT_TCP forKey:VSDECODER_OPT_KEY_RTSP_TRANSPORT]];
[_channelList addObject:c2];
Channel *c3 = [Channel channelWithName:#"Sky-news" addr:#"rtsp://202.65.154.103:1935/live/text.stream" description:#"justin reporter Alapati" options:[NSDictionary dictionaryWithObject:VSDECODER_OPT_VALUE_RTSP_TRANSPORT_TCP forKey:VSDECODER_OPT_KEY_RTSP_TRANSPORT]];
[_channelList addObject:c3];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onVSPlayerStateChanged:) name:kVSPlayerStateChangedNotification object:nil];
}
return self;
;
}
and then using tableView methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_channelList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellId = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId] autorelease];
UIView *topLine = [[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)] autorelease];
topLine.backgroundColor = [UIColor colorWithRed:1.1 green:1.1 blue:1.11 alpha:0.5];
[cell.contentView addSubview:topLine];
UIView *bottomLine = [[[UIView alloc] initWithFrame:CGRectMake(0.0f, 63.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)] autorelease];
bottomLine.backgroundColor =[UIColor colorWithRed:0.78 green:0.78 blue:0.79 alpha:0.5];
[cell.contentView addSubview:bottomLine];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:18];
cell.detailTextLabel.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:16];
}
Channel *channel = [_channelList objectAtIndex:indexPath.row];
cell.textLabel.text = [channel name];
cell.detailTextLabel.text = [channel description];
return cell;
}
- (void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath {
cell.backgroundColor = [UIColor colorWithRed:0.94 green:0.94 blue:0.95 alpha:1.0];
}
and then using didSelectRowAtIndexPath in
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Channel *channel = [_channelList objectAtIndex:indexPath.row];
NSString *urlString = [channel urlAddress];
NSDictionary *options = [channel options];
VSPlayerViewController *playerVc = [[[VSPlayerViewController alloc] initWithURL:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] decoderOptions:options] autorelease];
playerVc.barTitle = [channel name];
playerVc.statusBarHidden = YES;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
if ([[[UIDevice currentDevice] systemVersion] compare:#"6.0" options:NSNumericSearch] != NSOrderedAscending) {
//running on iOS 6.0 or higher
[self.navigationController presentViewController:playerVc animated:YES completion:NULL];
} else {
//running on iOS 5.x
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
[self.navigationController presentModalViewController:playerVc animated:YES];
#endif
}
#else
[self.navigationController presentModalViewController:playerVc animated:YES];
#endif
}
when click TableViewCell it open and play video portrait mode using RTSP protocal
but My requirement is When click TableViewCell it open and play video in landscape mode with out Mobile Rotation
Please give any idea
Thanks in advanced

In VSPlayerViewController class, viewWillAppear/viewDidLoad method:
//rotate rect
self.view.transform = CGAffineTransformMakeRotation(M_PI_2);
Hope this helps.

Related

UISearchBar Text Not Updating List of File Names

In my class for my TableView, I populate the rows with the names of all files within a given folder of my app. I am just now changing it over to UISearchBar, and I'm having some issues with my logic. The search bar appears, but the tableview simply goes blank.
In my .h file I have:
#interface DevoSongs : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchResultsUpdating >{
NSArray *files;
NSIndexPath *thepath;
NSString *filenames;
NSArray *try2;
NSMutableArray *searchResults;
NSString *savedSearchTerm;
IBOutlet UITableView *tableView;
}
#property (nonatomic, retain) UITableView *tableView;
#property (strong, nonatomic) UISearchController *searchController;
#property (nonatomic, retain) NSArray *files;
#property (nonatomic, retain) NSString *filenames;
#property (nonatomic, retain) NSIndexPath *thepath;
#property (nonatomic, retain) NSArray *try2;
#property (nonatomic, retain) NSMutableArray *searchResults;
#property (nonatomic, copy) NSString *savedSearchTerm;
- (void)handleSearchForTerm:(NSString *)searchTerm;
#end
For my implementation:
-(void)viewDidLoad {
[super viewDidLoad];
self.searchController = [[UISearchController alloc]
initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
[self.searchController.searchBar sizeToFit];
}
- (void)viewWillAppear:(BOOL)animated {
NSBundle *bundle = [NSBundle mainBundle];
self.files = [bundle pathsForResourcesOfType:#"pdf" inDirectory:#"thepdfpowerpoints"];
NSString *documentsDirectoryPath = [self.files objectAtIndex:thepath.row];
self.title = #"Devo Songs";
self.filenames = [[documentsDirectoryPath lastPathComponent] stringByDeletingPathExtension];
NSMutableArray *names = [NSMutableArray arrayWithCapacity:[self.files count]];
for (NSString *path in self.files) {
[names addObject:[[path lastPathComponent] stringByDeletingPathExtension]];
}
self.files = [names sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.backgroundColor = [UIColor darkGrayColor];
self.view.backgroundColor = [UIColor grayColor];
[super viewWillAppear:animated];
}
- (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.
if (self.searchController.isActive) {
return [searchResults count];
}
else {
return [self.files count];
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *filename = [[[self.files objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension];
NSInteger row = [indexPath row];
NSString *contentForThisRow = nil;
contentForThisRow = filename;
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
[[cell textLabel] setText:contentForThisRow];
cell.textLabel.font = [UIFont fontWithName:#"Roboto-Bold" size:38];
cell.textLabel.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor blackColor];
return cell;
}
else {
[[cell textLabel] setText:contentForThisRow];
cell.textLabel.font = [UIFont fontWithName:#"Roboto-Bold" size:22];
cell.textLabel.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor darkGrayColor];
return cell;
}
}
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope{
[self updateSearchResultsForSearchController:self.searchController];
}
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController{
NSString *searchString = self.searchController.searchBar.text;
NSPredicate *resultPredicate;
resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",searchString];
searchResults = [self.files filteredArrayUsingPredicate:resultPredicate];
NSLog(#"results %lu", (unsigned long)[self.files count]);
[self.tableView reloadData];
}
Remove below code or comment below
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope{
[self updateSearchResultsForSearchController:self.searchController];}
Added the another searchController delegate method in your called show below.
- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange (NSRange)range replacementText:(NSString *)text {
[self updateSearchResultsForSearchController:self.searchController];}
This should work. Hope it help :)

How to pass a UIImageView from UITableView (custom cell) to DetailViewController?

I'm tearing my hair out over this one. I'm trying to pass an image URL from my TableViewController to my DetailViewController (FullArticleViewController) so that I can set the UIImageView, and nothing I try seems to be working. See my code below:
MyTableViewController.h
#interface MyTableViewController : UIViewController <UISearchBarDelegate>{
IBOutlet UITableView *DoctorsTableView;
NSArray *Doctors;
NSMutableData *data;
NSArray *searchResults;
}
#property (strong, nonatomic) NSString *cellImageLink;
#property (strong, nonatomic) UINavigationBar *navigationBar;
MyTableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *DoctorsTableIdentifier = #"DoctorsCell";
DoctorsCell *cell = (DoctorsCell *)[tableView dequeueReusableCellWithIdentifier:DoctorsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"DoctorsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSLog(#"Using the search results");
cell.firstnameLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:#"node_title"];
cell.descriptionLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:#"Opening Paragraph"];
NSString *firstLink = [[NSString alloc] init];
firstLink = [[[searchResults objectAtIndex:indexPath.row] objectForKey:#"Image"] objectForKey:#"filename"];
NSString *secondLink = [[NSString alloc] init];
secondLink = [NSString stringWithFormat:#"URL HERE%#",firstLink];
NSLog(#"second link is %#", secondLink);
cellImageLink = secondLink;
[cell.featureImage sd_setImageWithURL:[NSURL URLWithString:secondLink]];
} else {
NSLog(#"Using the Full List!");
cell.firstnameLabel.text = [[Doctors objectAtIndex:indexPath.row] objectForKey:#"node_title"];
cell.descriptionLabel.text = [[Doctors objectAtIndex:indexPath.row] objectForKey:#"Opening Paragraph"];
NSString *firstLink = [[NSString alloc] init];
firstLink = [[[Doctors objectAtIndex:indexPath.row] objectForKey:#"Image"] objectForKey:#"filename"];
NSString *secondLink = [[NSString alloc] init];
secondLink = [NSString stringWithFormat:#"URL HERE%#",firstLink];
NSLog(#"second link is %#", secondLink);
cellImageLink = secondLink;
[cell.featureImage sd_setImageWithURL:[NSURL URLWithString:secondLink]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FullArticleViewController *detailViewController = [[FullArticleViewController alloc]
initWithNibName:#"FullArticleViewController" bundle:nil];
if ([searchResults count]) {
detailViewController.title = [[searchResults objectAtIndex:indexPath.row] objectForKey:#"node_title"];
detailViewController.articleDetail = [searchResults objectAtIndex:indexPath.row];
} else {
detailViewController.title = [[Doctors objectAtIndex:indexPath.row] objectForKey:#"node_title"];
detailViewController.articleDetail = [Doctors objectAtIndex:indexPath.row];
NSLog(#"%#", Doctors);
}
FullArticleViewController *viewController = [[FullArticleViewController alloc]
initWithNibName:#"DetailViewController"
bundle:nil];
viewController.featureImage = searchResults[indexPath.row][#"Image"][#"filename"];
[self.navigationController pushViewController:detailViewController animated:YES];
}
FullArticleViewController.h (detailview)
#interface FullArticleViewController : UIViewController
{
IBOutlet UIScrollView *scroller;
IBOutlet UILabel *firstnameLabel;
IBOutlet UILabel *descriptionLabel;
IBOutlet UILabel *bodyLabel;
}
#property (nonatomic, copy) NSDictionary *articleDetail;
#property (strong, nonatomic) IBOutlet UIImageView *featureImage;
-(IBAction)goBack:(id)sender;
FullArticleViewController.m (detailview)
#import "SDWebImage/UIImageView+WebCache.h"
#import "FullArticleViewController.h"
#import "DoctorsCell.h"
#import "MyTableViewController.h"
#interface FullArticleViewController ()
#end
#implementation FullArticleViewController
#synthesize articleDetail;
#synthesize featureImage;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
featureImage = [[UIImageView alloc] init];
[scroller setScrollEnabled:YES];
[scroller setContentSize:CGSizeMake(320, 5000)];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
firstnameLabel.text = [articleDetail objectForKey:#"node_title"];
descriptionLabel.text = [articleDetail objectForKey:#"Opening Paragraph"];
bodyLabel.text = [articleDetail objectForKey:#"Body"];
}
MyTableViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FullArticleViewController *detailViewController = [[FullArticleViewController alloc]
initWithNibName:#"FullArticleViewController" bundle:nil];
if ([searchResults count]) {
detailViewController.title = [[searchResults objectAtIndex:indexPath.row] objectForKey:#"node_title"];
detailViewController.articleDetail = [searchResults objectAtIndex:indexPath.row];
detailViewController.cellImageLink = searchResults[indexPath.row][#"Image"][#"filename"];
} else {
detailViewController.title = [[Doctors objectAtIndex:indexPath.row] objectForKey:#"node_title"];
detailViewController.articleDetail = [Doctors objectAtIndex:indexPath.row];
detailViewController.cellImageLink = Doctors[indexPath.row][#"Image"][#"filename"];
}
NSLog(#"cellImageLink = %#", detailViewController.cellImageLink);
[self.navigationController pushViewController:detailViewController animated:YES];
}
FullArticleViewController.m
Set the image in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"cellImageLink = %#", self.cellImageLink);
featureImage = [[UIImageView alloc] init];
//maybe set the frame here?
[self.featureImage sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://domainnamehere.com/%#",cellImageLink]]];
[scroller setScrollEnabled:YES];
[scroller setContentSize:CGSizeMake(320, 5000)];
firstnameLabel.text = [articleDetail objectForKey:#"node_title"];
descriptionLabel.text = [articleDetail objectForKey:#"Opening Paragraph"];
bodyLabel.text = [articleDetail objectForKey:#"Body"];
}
Typically you would set detail view properties upon cell selection right before pushing the new view controller. Something like this would do it:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
FullArticleViewController *detailView = [[FullArticleViewController alloc] init];
detailView.articleDetail = [searchResults objectAtIndex:indexPath.row];
[self.navigationController pushViewController detailView animated:YES];
}
Notice I am using the default initializer for your view controller and am also assuming you are using a UINavigationController. You may need to change one or both of these to fit your code.
Then, you would want to use the same SDWebImage category to set the image url in viewDidLoad of FullArticleViewController.m. It will probably look something like this:
- (void)viewDidLoad
{
[scroller setScrollEnabled:YES];
[scroller setContentSize:CGSizeMake(320, 5000)];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
firstnameLabel.text = [articleDetail objectForKey:#"node_title"];
descriptionLabel.text = [articleDetail objectForKey:#"Opening Paragraph"];
bodyLabel.text = [articleDetail objectForKey:#"Body"];
[self.featureImage sd_setImageWithURL::[NSURL URLWithString:[[self.articleDetail objectForKey:#"Image"] objectForKey:#"filename"]];
}

UITableview paging crash aplication after loading 600 rows

I have a one major issue. I have implemented a uitable view with paging but when i reach to row 700 application crashed also sometimes it restart the ipad. So i tried every thing but i am not getting solution. this is my code.
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (dataArray.count<[self.allRecordCount intValue])
{
return dataArray.count+1;
}
return dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (dataArray.count<[self.allRecordCount intValue])
{
if (indexPath.row < dataArray.count) {
return [self dataCellForIndexPath:indexPath tableview:tableView];
} else {
return [self loadingCell];
}
}else{
return [self dataCellForIndexPath:indexPath tableview:tableView];
}
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (cell.tag == kLoadingCellTag) {
[self fillDataArray];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 150;
}
#pragma mark PAGING_LOGIC
-(void)fillDataArray
{
self.strStartPoint=[NSString stringWithFormat:#"%d",[dataArray count]];
self.strPageSize=[NSString stringWithFormat:#"%d",kPageSize];
NSMutableArray *temp=[manager returnCallArray:self.strStartPoint NoofRecord:self.strPageSize];
for (Call *obj in temp)
{
[dataArray addObject:obj];
}
[temp release];
[tbl reloadData];
}
- (UITableViewCell *)loadingCell {
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil] autorelease];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityIndicator.frame=CGRectMake(480.5f,52.5f , 45, 45);
[cell addSubview:activityIndicator];
[activityIndicator release];
[activityIndicator startAnimating];
cell.tag = kLoadingCellTag;
return cell;
}
- (UITableViewCell *)dataCellForIndexPath:(NSIndexPath *)indexPath tableview:(UITableView *)table
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%d %d",indexPath.section,indexPath.row];
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier];
if(table.tag == 0){
//cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *lblCall;UILabel *lblCallText;UILabel *lblAirComment;UILabel *lblCustomerTxt;UILabel *lblProximityTxt;
UILabel *lblNoOfMachineTxt;
UILabel *lblCallReceiveTxt;
UILabel *lblCallDueTxt;
if (cell==nil) {
Call *temp = [dataArray objectAtIndex:indexPath.row];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
lblCall = [[UILabel alloc]initWithFrame:CGRectMake(20,setY,220,20)];
lblCall.backgroundColor = [UIColor clearColor];
lblCall.text = #"Call Priority/Type/Status";
[cell.contentView addSubview:lblCall];
[lblCall release];
lblCallText = [[UILabel alloc]initWithFrame:CGRectMake(220,setY,270,20)];
lblCallText.backgroundColor = [UIColor clearColor];
lblCallText.tag = indexPath.row+100;
[cell.contentView addSubview:lblCallText];
[lblCallText release];
lbl_strstatusChangeReason = [[UILabel alloc] init];/
lbl_strstatusChangeReason.frame=CGRectMake(20,setY,800, labelSize5.height);
lbl_strstatusChangeReason.backgroundColor = [UIColor clearColor];
lbl_strstatusChangeReason.text = str_changeStatusReasoon;
lbl_strstatusChangeReason.tag = indexPath.row + 200000;
lbl_strstatusChangeReason.numberOfLines = 0;
lbl_strstatusChangeReason.lineBreakMode = UILineBreakModeWordWrap;
lbl_strstatusChangeReason.textColor = [UIColor redColor];
[cell.contentView addSubview:lbl_strstatusChangeReason];
}
return cell;
}
This is my NSObject which i use for filling cell.
#import <Foundation/Foundation.h>
#interface Call : NSObject {
NSString *strType;
NSString *strTypePriority;
NSString *strCustomer;
NSString *strProximity;
NSString *strETADateTime;
NSString *str480;
NSString *strAirComment;
NSString *strProblemDesc;
NSString *strNumberOfMachine;
NSString *strCallReceived;
NSString *strCallDue;
NSString *strAssignedTech;
NSString *strAssignedTechName;
NSString *strDefaultTech;
NSString *strDefaultTechName;
NSString *strDispatchedBy;
}
#property(nonatomic,retain)NSString *strDispatchedToTechInterval;
#property(nonatomic,retain)NSString *strDispatchedToBranchInterval;
#property(nonatomic,retain)NSString *strDispatchToTechnicianDate;
#property(nonatomic,retain)NSString *strDispatchToTechnicianTime;
#property(nonatomic,retain)NSString *strDispatchToTechnicianFrom;
#property(nonatomic,retain)NSString *strDispatchToTechnicianBy;
#property(nonatomic,retain)NSString *strCallClosedDateAndTimeSorting;
#property(nonatomic,retain)NSString *strCallClosedDateAndTime;
#property(nonatomic,retain)NSString *strCallClosedDate;
#property(nonatomic,retain)NSString *strCallClosedTime;
#property(nonatomic,retain)NSString *strtotalAmount;
#property(nonatomic,retain)NSString *strtotalPartAmount;
#property(nonatomic,retain)NSString *strtotalChargeAmount;
#property(nonatomic,retain)NSString *strOriginatingFacility;
#property(nonatomic,retain)NSString *str_RecordVersionNumber;
#property(nonatomic,retain)NSString *str_CustomerLatitude;
#property(nonatomic,retain)NSString *str_CustomerLongitude;
#property(nonatomic,retain)NSString *strDiscount;
#property(nonatomic,retain)NSString *str_HdrComment1;
#property(nonatomic,retain)NSString *str_PrioritySortValue;
#property(nonatomic,retain)NSString *str_StatusChangeReason;
#property(nonatomic,retain)NSString *str_OnSiteDate;
#property(nonatomic,retain)NSString *str_Address;
#property(nonatomic,retain)NSString *str_Address1;
#property(nonatomic,retain)NSString *str_Address2;
#property(nonatomic,retain)NSString *str_City;
#property(nonatomic,retain)NSString *str_State;
#property(nonatomic,retain)NSString *str_Zip;
#property(nonatomic,retain)NSString *strStatus;
#property(nonatomic,retain)NSString *strTypePriority;
#property(nonatomic,retain)NSString *strCustomer;
#property(nonatomic,retain)NSString *strProximity;
#property(nonatomic,retain)NSString *str480;
#property(nonatomic,retain)NSString *strAirComment;
#property(nonatomic,retain)NSString *strProblemDesc;
#property(nonatomic,retain)NSString *strNumberOfMachine;
#property(nonatomic,retain)NSString *strCallReceived;
#property(nonatomic,retain)NSString *strCallDue;
#property(nonatomic,retain)NSString *strAssignedTech;
#property(nonatomic,retain)NSString *strDefaultTech;
#property(nonatomic,retain)NSString *strDispatchedBy;
#end
#import "Call.h"
#implementation Call
#synthesize strStatus;
#synthesize strTypePriority;
#synthesize strCustomer;
#synthesize strProximity;
#synthesize str480;
#synthesize strAirComment;
#synthesize strProblemDesc;
#synthesize strNumberOfMachine;
#synthesize strCallReceived;
#synthesize strCallDue;
#synthesize strAssignedTech;
#synthesize strDefaultTech;
#synthesize strDispatchedBy;
#synthesize strCallNumber;
#synthesize strHoldCall;
#synthesize strOpenCall;
#synthesize strLoactionId;
#synthesize strCustomerName;
#synthesize strContactName;
#synthesize strPhoneNo;
#synthesize strFirsMachine;
#synthesize strMachineDone;
#synthesize strDispatchedToBranch;
#synthesize strDispatchedToTech;
#synthesize strServiceDue;
#synthesize strCallComment;
#synthesize strDiscount;
- (void)dealloc {
[strStatus release];
[strTypePriority release];
[strCustomer release];
[strProximity release];
[str480 release];
[strAirComment release];
[strProblemDesc release];
[strNumberOfMachine release];
[strCallReceived release];
[strCallDue release];
[strAssignedTech release];
[strDefaultTech release];
[strDispatchedBy release];
[strCallNumber release];
[strHoldCall release];
[strOpenCall release];
[strLoactionId release];
[strCustomerName release];
[strContactName release];
[strPhoneNo release];
[strFirsMachine release];
[strMachineDone release];
[strDispatchedToBranch release];
[strDispatchedToTech release];
[strServiceDue release];
[strCallComment release];
[strDiscount release];
[str_StatusChangeReason release];
[super dealloc];
}
and this is my method which i am using for filling array for paging.
-(NSMutableArray *)returnCallArray:(NSString *)startPoint NoofRecord:(NSString *)noOfRecord
{
[self initiateFMDB];
NSMutableArray *aryCallFilterData=[[NSMutableArray alloc]init];
// NSMutableArray *finalArrayCall=[[NSMutableArray alloc]init];
#try {
if(![db open]){
NSLog(#"Could not open DB");
}
else{
resultset = [db executeQuery:[NSString stringWithFormat:#"select Call_HDR.*,Problem.Machine,Problem.ServiceStatusFlag,AssignTech.RepName AS AssignTechName,DefaultTech.RepName AS DefaultTechName,Problem.ProblemDescription AS ProblemDescription,Problem.SLAHours AS SLAHours,ARComment.CustARComments As CustARComments,SLAResponseCode.SLAResponse As SLAResponse from CALL_HDR LEFT JOIN Branch_Reps as AssignTech ON CALL_HDR.RepID = AssignTech.RepID LEFT JOIN Branch_Reps as DefaultTech ON CALL_HDR.AssignedServiceRep = DefaultTech.RepID LEFT JOIN CALL_MACHINE as Problem ON CALL_HDR.CallNumber||'*001' = Problem.CallNumberWSeqnbr LEFT JOIN Customers as ARComment ON CALL_HDR.LocationID = ARComment.LocationID LEFT JOIN NA_Data as SLAResponseCode ON CALL_HDR.CustomerTypeCode = SLAResponseCode.NationalAccountCode where CALL_HDR.CallStatus IN ('%#','%#') LIMIT %#,%# ",STATUS_CLOSED,STATUS_CANCELLED,startPoint,noOfRecord]];
}
}
#catch (NSException * e) {
NSLog(#"Exception error for selectFromItemPhoto is %#",[e reason]);
}
if (!resultset) {
NSLog(#"no result set fechted");
}
while ([resultset next]) {
NSString *strCallPrioritySortValue = [resultset stringForColumn:#"PrioritySortValue"];
NSString *strCallPriority = [resultset stringForColumn:#"CallPriority"];
NSString *strCallType = [resultset stringForColumn:#"CallType"];
NSString *strCallStatus = [resultset stringForColumn:#"CallStatus"];
NSString *strCustomerName = [resultset stringForColumn:#"CustomerName"];
NSString *strAdd1 = [resultset stringForColumn:#"Address1"];
NSString *strAdd2 = [resultset stringForColumn:#"Address2"];
NSString *strCity = [resultset stringForColumn:#"City"];
NSString *strState = [resultset stringForColumn:#"State"];
NSString *strZip = [resultset stringForColumn:#"Zip"];
NSString *strCustomer=#"";
ObjModel.strStsChgByRep=strStatusChgByRep;
ObjModel.strCustomer = strCustomer;
ObjModel.strStatus = strCallStatus;
ObjModel.strHoldCall =strHoldCode;
ObjModel.strProximity = #"";
ObjModel.f_proximity = 0.0f;
ObjModel.str480 = strStr480;
ObjModel.strProblemDesc = strProbleDesc;
ObjModel.strNumberOfMachine =strNumberOfMachine;
ObjModel.strCallReceived = strCallReceive;
ObjModel.strCallDue = strCallDue;
ObjModel.strAssignedTech = strAssignedTech;
ObjModel.strDefaultTech = strDefaultTech;
ObjModel.strDispatchedBy = strDispatchedBy;
ObjModel.strCallNumber = strCallNumber;
ObjModel.n_CallNumber = [strCallNumber intValue];
ObjModel.strLoactionId = strLoactionId;
ObjModel.strContactName = strContactName;
ObjModel.strCustomerName = strCustomerName;
ObjModel.strPhoneNo = strPhoneNo;
ObjModel.strDiscount = strDisct;
ObjModel.strAirComment = strAirComment;
ObjModel.strAssigntechName = strAssignedTechBy;
ObjModel.strRepId = strRepId;
ObjModel.str_Address1 = strAdd;
ObjModel.str_StatusChangeReason = strStatusChangeReason;
[aryCallFilterData addObject:ObjModel];
[ObjModel release];
}
return aryCallFilterData;
}
So please review my code and suggest something so that i can resolve crash.
This is crash log:
Received memory warning.
2013-06-24 04:59:26.168 MFSS_PAGING_FACEBOOK[874:907] <FMDatabase: 0x2d8aa130> executeQuery: select Call_HDR.*,Problem.Machine,Problem.ServiceStatusFlag,AssignTech.RepName AS AssignTechName,DefaultTech.RepName AS DefaultTechName,Problem.ProblemDescription AS ProblemDescription,Problem.SLAHours AS SLAHours,ARComment.CustARComments As CustARComments,SLAResponseCode.SLAResponse As SLAResponse from CALL_HDR LEFT JOIN Branch_Reps as AssignTech ON CALL_HDR.RepID = AssignTech.RepID LEFT JOIN Branch_Reps as DefaultTech ON CALL_HDR.AssignedServiceRep = DefaultTech.RepID LEFT JOIN CALL_MACHINE as Problem ON CALL_HDR.CallNumber||'*001' = Problem.CallNumberWSeqnbr LEFT JOIN Customers as ARComment ON CALL_HDR.LocationID = ARComment.LocationID LEFT JOIN NA_Data as SLAResponseCode ON CALL_HDR.CustomerTypeCode = SLAResponseCode.NationalAccountCode where CALL_HDR.CallStatus IN ('8','0') LIMIT 700,100
Thanks
You should reuse your cells. You have so many UITableViewCells loaded into memory and it crashes after a memory warning.
You cell identifier (index+row) create as many cells as 700, when you are loading 700 rows of data. The cell identifier should be unique to the number of cells shown in the screen, not more than that. Best is, you can have some other easy and non looping cell identifier. So cells are reused more efficiently.
Try to use the same UITableViewCell but change the labels and detailLabels matching with your information to show.
One thing that is worth looking at is the dequeueReusableCellWithIdentifier use in your code. from what i can tell you are creating a new cell for each data item because you are using the cell section and row as and identifier. Is there a reason for this? If your cells are visually the same (Only the data for each is different) then change this so the dequeueReusableCell identifier is the same for each cell. This gives the OS the ability to manage the memory for cells more efficiently.

iOS UITableView content not loading - Property access result unused

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

GCD and KVO problems

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.

Resources