I am currently making a Facebook application for iOS that pulls the profile feed and puts it in a UITableView.
Right Now When the View Loads:
[facebook requestWithGraphPath:#"me/feed" andDelegate:self];
and in -(void)request:(FBRequest *)request didLoad:(id)result, i have:
NSArray *messagesFBData = [result objectForKey:#"data"];
NSMutableArray *friendIds = [NSMutableArray arrayWithCapacity:messagesFBData.count];
NSMutableArray *fromData = [NSMutableArray arrayWithCapacity:messagesFBData.count];
NSMutableArray *imagesLocal = [NSMutableArray arrayWithCapacity:messagesFBData.count];
for (int x = 0; x < messagesFBData.count; x++) {
if ([(NSDictionary *)[messagesFBData objectAtIndex:x] objectForKey:#"message"] != nil) {
[friendIds addObject:[((NSDictionary*)[messagesFBData objectAtIndex:x]) objectForKey:#"message"]];
NSLog(#"loop Log: %#", [(NSDictionary *)[messagesFBData objectAtIndex:x] objectForKey:#"message"]);
[fromData addObject:[((NSDictionary*)[messagesFBData objectAtIndex:x]) objectForKey:#"from"]];
NSLog(#"%#", [((NSDictionary*)[messagesFBData objectAtIndex:x]) objectForKey:#"from"] );
NSDictionary *fromDataDictionary = [fromData objectAtIndex:x];
[imagesLocal addObject:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture", [fromDataDictionary objectForKey:#"id"]]]]]];
NSLog(#"facebook ID: %#", [fromDataDictionary objectForKey:#"id"]);
} else
{
NSLog(#"Nil Called");
}
}
// don't forget to call loadData for your tableView
messages = friendIds;
images = imagesLocal;
NSLog(#"Equalized");
self.facebookTableView.delegate = self;
NSLog(#"Delegate Set");
[facebookTableView reloadData];
images is a global array, so i can access it in -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.
so in -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, i have:
NSLog(#"Cell For Row Called");
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"messageCell"];
NSString *story = [messages objectAtIndex:indexPath.row];
cell.textLabel.text = story;
UIImage *image = [images objectAtIndex:indexPath.row];
cell.imageView.image = image;
cell.alpha = 1;
return cell;
So the question I am having a horrible time with is when a user posts a picture or video on the wall, how do i handle that? I would like to display the image/video in the tableview itself. Right Now, it just crashes. Any help would be greatly appreciated.
Thanks,
Virindh Borra
At what point is it crashing? Did you place any breakpoints in the code? When you add the UIImage to the imagesLocal array, are you the path at "https://graph.facebook.com/%#/picture" contains a valid image?
Related
Hi I am trying to display detail information of json data in second table view but their is some mistake in my logic so please help me my json response is in image and I am trying to to dispaly channel response in table view when user click the same cat_id then display all related channel list and image in second tableViewcell please help me..
-(void)getCategories
{
Service *srv=[[Service alloc]init];
NSString *str=#"http://streamtvbox.com/site/api/matrix/";//?country_code=91&phone=9173140993&fingerprint=2222222222";
NSString *method=#"channels";
NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
[srv postToURL:str withMethod:method andParams:dict completion:^(BOOL success, NSDictionary *responseObj)
{
NSDictionary *dict = [[NSDictionary alloc]initWithDictionary:[responseObj valueForKey:#"categories"]];
arrayChannelList=[responseObj valueForKey:#"channels"];
NSLog(#"Array : %#",channels);
for (NSDictionary *dict in arrayChannelList)
{
//NSArray *tempTitle = [[NSArray alloc]init];
arrayCat_Id = [dict objectForKey:#"cat_id"];
}
tempArray = [[NSArray alloc]init];
tempArray = [dict allKeys];
for(int i=0; i<tempArray.count; i++)
{
[arrayCategories addObject:[dict valueForKey:[tempArray objectAtIndex:i]]];
}
NSLog(#"%#",arrayCategories);
[tblView reloadData];
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%lu",(unsigned long)[arrayCategories count]);
return arrayCategories.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ChannelCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [arrayCategories objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailChannelsViewController *detailVC = (DetailChannelsViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"DetailView"];
detailVC.channelTitle = [arrayCategories objectAtIndex:indexPath.row];
detailVC.SubChannelName = arrayCat_Id;
NSLog(#"%#",arrayCat_Id);
[self.navigationController pushViewController:detailVC animated:YES];
}
Just initialize of your NSmutuableArray and add the value of with addobject like:-
arrayCat_Id=[[NSMutableArray alloc]init];
for(your logic){
[arrayCat_Id addobject:[dict objectForKey:#"cat_id"];
}
I'm attempting to allow my user to be able to delete/remove a row from a tableView (remove an object from an existing NSMutableArray), however when I try and delete the row, I get the following crash error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: '-[__NSCFArray
removeObjectAtIndex:]: mutating method sent to immutable object'
Does anyone know why this might be? See code below. Apologies for the lengthy code.
.h
#property (strong, nonatomic) NSMutableArray *descripData;
.m
- (void)viewDidLoad {
[super viewDidLoad];
self.descripData = [[NSMutableArray alloc] init];
refreshControl = [[UIRefreshControl alloc]init];
[self.tableView addSubview:refreshControl];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:#"storeditems" forKey:#"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.descripData = responseObject;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.storageData count] > 0 && self.descripData.count > 0)
{
return [self.descripData count];
}
else
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *DoctorsTableIdentifier = #"StorageItemTableViewCell";
StorageItemTableViewCell *cell = (StorageItemTableViewCell *)[tableView dequeueReusableCellWithIdentifier:DoctorsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StorageItemTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (self.storageData.count > 0 && self.descripData.count > 0) {
noitemsView.hidden = YES;
NSDictionary *title = [self.descripData objectAtIndex:indexPath.row];
[[cell itemName] setText:[title objectForKey:#"node_title"]];
NSDictionary *node = [self.descripData objectAtIndex:indexPath.row];
[[cell itemDescrip] setText:[node objectForKey:#"body"]];
NSDictionary *value = [self.descripData objectAtIndex:indexPath.row];
[[cell valueLabel] setText:[value objectForKey:#"dollarvalue"]];
NSLog(#"%#", self.descripData);
NSDictionary *quantity = [self.descripData objectAtIndex:indexPath.row];
[[cell quantityLabel] setText:[quantity objectForKey:#"quantity"]];
NSLog(#"%#", self.descripData);
NSString *secondLink = [[self.descripData objectAtIndex:indexPath.row] objectForKey:#"photo"];
[cell.itemPhoto sd_setImageWithURL:[NSURL URLWithString:secondLink]];
}
else {
noitemsView.hidden = NO;
}
return cell;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 152;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[self.descripData removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadData];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ItemDetailViewController *detailViewController = [[ItemDetailViewController alloc] initWithNibName:#"ItemDetailViewController" bundle:nil];
detailViewController.itemDetail = [[values objectAtIndex:indexPath.row] objectForKey:#"node_title"];
detailViewController.itemDetail = [self.descripData objectAtIndex:indexPath.row];
detailViewController.secondLink = self.descripData[indexPath.row][#"photo"];
[self.navigationController pushViewController:detailViewController animated:YES];
}
Check the line self.descripData = responseObject;. It looks like you are probably setting your descripData property to point to a NSArray, not an NSMutableArray. If you really need the mutability, try self.descripData = [responseObject mutableCopy]; instead.
I suspect that the following assignment causes the problem:
self.descripData = responseObject;
The response object itself is immutable, assigning it to a NSMutableArray does not change that fact, you need to create a NSMutableArray with the contents of the responseObject:
self.descripData = [NSMutableArray arrayWithArray:responseObject];
Most likely happening on the following line:
self.descripData = responseObject;
You're replacing your previous mutable array for descripData with a new one, which apparently is not mutable. You can either create a new mutable array from this new array using [NSMutableArray arrayWithArray:responseObject], or you can add the contents of responseObject to your current mutable array.
It's important to pay attention when you assign something of type id to a variable, because there's no compile-time type checking that can occur. This sometimes results in errors at runtime.
Face this issue because NSUserDefaults always returns an immutable object.
Please while retrieving Mutable object from NSUserDefaults please refer below code.
NSMutableArray *storeArray = [[defaultDefects objectForKey:#"defaultStoreDefects"]mutableCopy];
I have 2 tables view . One is with category and the other with videos .I added the favorite song into an array . But how can i reload my table with only the favorite videos when favorite category is selected ?
This is what i was trying but my table view is empty.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView.tag==0) {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell=[[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
cell.title.text=[[stories objectAtIndex: indexPath.row] objectForKey: #"title"];
NSString * aux=[[stories objectAtIndex: indexPath.row] objectForKey: #"url"];
NSString * videoHTML =[NSString stringWithFormat: #"<iframe type=\"text/html\" width=\"100\" height=\"80\" src=\"%#\" frameborder=\"0\"></iframe>",aux] ;
NSString *imagine=[[stories objectAtIndex:indexPath.row]objectForKey:#"thumbnail"];
cell.imageSong.image=[UIImage imageNamed:imagine];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imagine]];
cell.imageSong.image = [UIImage imageWithData:imageData];
cell.imageSong.contentMode=UIViewContentModeScaleAspectFit;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (!tableView.tag==0) {
int row =indexPath.row;
if (row==0) {
self.title1.text=#"ALL SONGS";
[stories removeAllObjects];
[self parse];
i=0;
[self showMenu:nil];
}
else if (row==1) {
self.title1.text=#"FAVORITE";
b=[favoriteArray count];
if (b==0) {
NSLog(#"NSArray empty");
[[[UIAlertView alloc]initWithTitle:#"Attention !" message:#"No videos !" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil]show];
}
else{
[stories removeAllObjects];
[self.tableView reloadData];
i=0;
[self showMenu:nil];
}
}
else
{
self.title1.text=[categoryArray objectAtIndex:indexPath.row-1];
[stories removeAllObjects];
NSString * path =[feeds objectAtIndex:indexPath.row-1];
[self parseXMLFileAtURL:path];
i=0;
[self showMenu:nil];}
self.karaokeBTn.hidden=YES;
self.menu.hidden=NO;
self.title1.hidden=NO;
}
-(void)parse{
if ([stories count] == 0) {
for (int i=0; i<[feeds count]; i++) {
NSString * path =[feeds objectAtIndex:i];
[self parseXMLFileAtURL:path];
}
}
}
In favorite array i already have the url for video, title and image . i dont need to parse the feed again.
Maybe you want to reload your table after parsing:
-(void)parse{
if ([stories count] == 0) {
for (int i=0; i<[feeds count]; i++) {
NSString * path =[feeds objectAtIndex:i];
[self parseXMLFileAtURL:path];
}
[self.tableView reloadData];
}
I'm not exactly sure if I understood your issue. But since you said your tableView is empty heres a possible solution.
How do you set stories array? If it's a asynchronous data fetch from web, you have a empty stories array when those delegate methods get called.
You have to reload table view once data fetching is done. On the completion block of your data fetching method.
[self.tableView reloadData];
I have a UITableView that loads content from a server.
All works fine and the content loads correctly, but when I scroll my UITableView lags a bit.
I created a method that downloads the content from a server, and I call this method in my viewDidLoad method, since it is the first thing that opens when I open the app.
I don't know if this is the best approach.
How I can avoid that? Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Method that Loads the Content
[self retrieveData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Retorna o nĂºmero de linhas pelo array de programacao.
return programacaoArray.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// ALTURA da TableViewCell
return 150;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CellIdentifier";
ProgramacaoTableCell *cell = (ProgramacaoTableCell *)[self.tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[ProgramacaoTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
// Configure the Cell
Programacao *programacaoObject;
programacaoObject = [programacaoArray objectAtIndex:indexPath.row];
cell.atracaoImagem.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:programacaoObject.programacaoImagem]]];
cell.nomeLabel.text = programacaoObject.programacaoNome;
cell.dataLabel.text = programacaoObject.programacaoData;
cell.localLabel.text = programacaoObject.programacaoLocal;
return cell;
}
- (void) retrieveData
{
NSURL *url = [NSURL URLWithString:getDataURL];
NSData *data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// SETUP programacaoArray
programacaoArray = [[NSMutableArray alloc] init];
// Loop throught do Array
for (int i = 0; i < jsonArray.count; i++) {
// Cria o PROGRAMACAO Objeto
NSString *pID = [[jsonArray objectAtIndex:i] objectForKey:#"id"];
NSString *pNome = [[jsonArray objectAtIndex:i] objectForKey:#"programacaoNome"];
NSString *pImagem = [[jsonArray objectAtIndex:i] objectForKey:#"programacaoImagem"];
NSString *pDescricao = [[jsonArray objectAtIndex:i] objectForKey:#"programacaoDescricao"];
NSString *pData = [[jsonArray objectAtIndex:i] objectForKey:#"programacaoData"];
NSString *pLocal = [[jsonArray objectAtIndex:i] objectForKey:#"programacaoLocal"];
NSString *pPrecos = [[jsonArray objectAtIndex:i] objectForKey:#"programacaoPrecos"];
// Add to the Array
[programacaoArray addObject:[[Programacao alloc] initWithNome:pNome andImagem:pImagem andDescricao:pDescricao andData:pData andLocal:pLocal andPrecos:pPrecos andID:pID]];
}
// RELOAD TABLE VIEW
[self.tableView reloadData];
}
There's a very obvious mistake you're making. You're loading the image synchronously (on the same thread, which in this case is the main thread), which is what's causing the lag. You should look into using AFNetworking's UIImageView category, which will load these images in the background for you.
You can download the AFNetworking library from here.
I think cause problem by code:
'cell.atracaoImagem.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:programacaoObject.programacaoImagem]]];
you can use SDWebImage framework, loading image
I think you should call the retrieveData function in viewWillAppear method instead of viewDidLoad
My NSMutableArray seems to be releasing and I can't figure out where, here is my code:
- (void)awakeFromNib {
arrayOfData = [[NSMutableArray alloc] initWithCapacity:0];
[arrayOfData addObject:#"test"];
NSLog(#"array: %#", arrayOfData);
}
All is well here!
Then I create a UITable and add it to the view, then I request some data, everything is normal.
arrayOfData = [response objectForKey:#"results"];
NSLog(#"count: %i", [arrayOfData count]);
NSLog(#"success!");
numberOfRows = [arrayOfData count];
[self.myTableView reloadData];
Creating the number of rows works fine too:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"test: %i", numberOfRows);
return numberOfRows;
}
Now accessing my array gets a "message sent to deallocated instance" at that line.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// crashes here!
NSLog(#"array: %i", [arrayOfData count]);
if (numberOfRows){
NSString *filename = [[arrayOfData objectAtIndex:indexPath.row] objectForKey:#"filename"];
NSString *url = [NSString stringWithFormat: #"http://www.web.com/dir/%#", filename];
[cell.imageView setImageWithURL:[NSURL URLWithString:url]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
cell.textLabel.text = #"My Text";
}
return cell;
}
I have also have this in my header, and I used #synthesize as well
#property (nonatomic, retain) NSMutableArray *arrayOfData;
Any help would be appreciated!
It looks like you're reassigning arrayOfData with this line:
arrayOfData = [response objectForKey:#"results"];
If that's what you want, try this instead:
arrayOfData = [[response objectForKey:#"results"] retain];