variable becomes nil in numberOfRowsInTableView after being set in another method - objective-c

My class looks like this :
#interface ApplicantPickerController : AppPage <NSTableViewDataSource, NSTableViewDelegate>
{
School *school;
__weak IBOutlet NSTableView *tableView;
NSMutableArray *familyList;
__weak IBOutlet NSProgressIndicator *progressIndicator;
}
- (IBAction)alphabetButtonPressed:(id)sender;
#end
In the alphabetButtonPressed method, I'm fetching a json array from a webservice and assigning it to familyList. After doing this, I do [tableView reload];
When the control passes to the - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView method, familyList becomes nil. Why is this happening and how can I fix it?
I'm using ARC for this project.
Cocoa/Objective-C newbie here. Any help would be much appreciated. Thank you!
Updated - Here is the implementation of the class :
#interface ApplicantPickerController ()
#end
#implementation ApplicantPickerController
- (IBAction)alphabetButtonPressed:(id)sender {
[progressIndicator startAnimation:self];
NSString * addy = [[NSString alloc] initWithFormat:#"%#.php?function=applicant_lookup&schoolID=%#&alpha=%#&currentYear=%#&format=json", BASE_URL_SCHOOL, school->recordID, [sender title], school->CurrentYear];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:addy]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if(data) {
//NSString * resp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSError *error = nil;
NSObject *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if([json isKindOfClass:[NSDictionary class]])
{
familyList = nil;
[tableView reloadData];
}
else if ([json isKindOfClass:[NSArray class]])
{
familyList = [[NSMutableArray alloc] init];
[familyList addObjectsFromArray:(NSArray*)json];
//[_familyList retain];
[tableView reloadData];
}
[progressIndicator stopAnimation:self];
}
}];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [familyList count];
}
- (id)initWithMainView:(NSView *)_theView AndMainController:(NSViewController *)_theViewController AndNibName:(NSString *)nibName AndArgs:(NSArray *)_args
{
self = [super initWithMainView:_theView AndMainController:_theViewController AndNibName:nibName AndArgs:_args];
school = [args objectAtIndex:0];
return self;
}
#end

I don't know if I discovered a bug by apple, but following is how I solved this issue.
I was setting the NSTableView delegate and datasource in the UI builder (by right clicking and making the connections with the mouse). For some reason, if I set the delegate and dataSource in the code (specifically in the awakeFromNib method), the issue gets resolved.
- (void)awakeFromNib {
tableView.delegate = self;
tableView.dataSource = self;
}

Related

how can make Custom Delegate For Custom UIView objective c , OK button not working

Here is my affected code:
#import "AddTeamView.h"
#import <AFNetworking.h>
#implementation AddTeamView
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
self=[super initWithCoder:aDecoder];
if (self)
{
[self customInit];
}
return self;
}
-(instancetype)initWithFrame:(CGRect)frame
{
self=[super initWithFrame:frame];
if (self)
{
[self customInit];
}
return self;
}
-(void)customInit
{
[[NSBundle mainBundle]loadNibNamed:#"AddTeamView" owner:self options:nil];
[self addSubview:self.contentView];
}
- (IBAction)okButton:(UIButton *)sender
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *params = #{#"team_name":self.enterNameTextField.text
};
[manager POST:#"https://api.cartolafc.globo.com/times?q=team_name" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
}progress:nil success:^(NSURLSessionTask *task, id responseObject) {
// [self stopHud];
NSLog(#"JSON: %#", responseObject);
NSDictionary *response = (NSDictionary *)responseObject;
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSInteger statusCode = error.code;
NSLog(#"%ld",(long)statusCode);
// [self stopHud];
}];
}
I create a .Xib file like:
When I press on Ok button, the response doesn't come and nothing happens.
Now how can I declare custom Delegate for custom UIView
and why delegate is required here? Can anyone kindly explain what can I do to get the response of API?
Open your AddTeamView.h and this code.
#protocol AddTeamDelegate <NSObject>
- (IBAction)okButton:(UIButton *)sender;
#end
#property id <AddTeamDelegate> delegate;
And synthesize this property in AddTeamView.m file as below.
#synthesize delegate;
Add this code In your viewController.h file where you are adding AddTeamView as subview.
#interface ViewController : UIViewController <AddTeamDelegate>
In your viewController.m file add this code while adding AddTeamView as subView.
AddTeamView.delegate = self;
and add this method for Ok button in same file
- (IBAction)okButton:(UIButton *)sender
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *params = #{#"team_name":self.enterNameTextField.text
};
[manager POST:#"https://api.cartolafc.globo.com/times?q=team_name" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
}progress:nil success:^(NSURLSessionTask *task, id responseObject) {
// [self stopHud];
NSLog(#"JSON: %#", responseObject);
NSDictionary *response = (NSDictionary *)responseObject;
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSInteger statusCode = error.code;
NSLog(#"%ld",(long)statusCode);
// [self stopHud];
}];
}

Reload table after request was finished

I have a table view that use result of fetching data with NSURLSession as a datasource. Here is my NSArray which is responsible about that table.
#property (strong, nonatomic) NSMutableArray *results;
And this is my delegate and datasource method
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_results count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
WordResult *word = (WordResult *)[_results objectAtIndex:indexPath.row];
cell.textLabel.text = word.defid;
return cell;
}
In my viewDidLoad, I fetched request from Mashape and try to map the result into my custom class WordResult
Here is my fetch method
#pragma mark - GET Request
- (void)fetchDataFromMashape:(NSURL *)URL {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:#"GET"];
[request setValue:API_KEY_MASHAPE forHTTPHeaderField:API_MASHAPE_HEADER_1];
[request setValue:API_ACCEPT forHTTPHeaderField:API_MASHAPE_HEADER_2];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.results = [self processResultData:jsonResult];
}];
[task resume];
}
- (NSMutableArray *)processResultData:(NSDictionary *)dict {
NSArray *list = [dict objectForKey:#"list"];
NSMutableArray *tempListOfWord = [[NSMutableArray alloc] init];
if (list) {
for (NSDictionary *item in list) {
WordResult *word = [[WordResult alloc] initWithDictionary:item];
[tempListOfWord addObject:word];
}
}
NSLog(#"Result array of word: %#", tempListOfWord);
return tempListOfWord;
}
My problem is, I dont know where to reload data after my result array was assigned by fetch method and dismissing my progress HUD that I showed on my viewDidLoad.
Here is my viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
[SVProgressHUD show];
[self fetchDataFromMashape:_finalURLrequest];
}
So where should I put [SVProgressHUD dismiss] and [self.tableView reloadData] after my request has been finished?
Any help would be appreciated.
Reload your table on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadData];
});
A great tableView coding pattern is putting reload call in setters of model objects, then you won't miss any data change. For example setter for result in your case:
-(void)setResult:(NSMutableArray*)result{
_result = result;
[self.tableView reloadData]
[SVProgressHUD dismiss]
}
Try this:
You can put [SVProgress dismmis] and also reload your tableview [self.tableView reloadData] after self.results = [self processResultData:jsonResult];
In your viewdidload before calling fetchdata do
self.results=[[NSMutableArray alloc]init];
And then call your [self.tableView reloadData] within the completion block after assigning the array with data
And then call svprogress hud hide method outside the block after [task resume] in the fetch data function

Populating Custom TableViewCell from Twitter using JSON Serialization

I am new to Objective-C. I spent countless hours being stuck on getting a blank tableview, I am desperate at this point.
I am loading twitter data through a JSON call, using their API. I store everything in a NSDictionary, run a for loop to select only "text" values. I store the filtered dictionary in an object which I later use in the TableView initialization.
I created a subclass of UItableViewCell for my custom cell.
My dataSources and delegates seem to be well connected as well (that is what I think at least)
I am having a hard time finding my problem. If someone could help me out please.
#import "ViewController.h"
#import "myCell.h"
#import <TwitterKit/TwitterKit.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize myTableView;
NSMutableArray *tweetObject;
NSDictionary *dictionary;
NSString *name;
NSString *text;
- (void)viewDidLoad {
tweetObject = [[NSMutableArray alloc] init];
[super viewDidLoad];
self.myTableView.dataSource = self;
self.myTableView.delegate = self;
text = #"text";
[[Twitter sharedInstance] logInGuestWithCompletion:^(TWTRGuestSession *guestSession, NSError *error) {
if (guestSession) {
// make API calls that do not require user auth
NSString *statusesShowEndpoint = #"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=goofernator";
NSError *clientError;
NSURLRequest *request = [[[Twitter sharedInstance] APIClient]
URLRequestWithMethod:#"GET"
URL:statusesShowEndpoint
parameters:0
error:&clientError];
if (request) {
[[[Twitter sharedInstance] APIClient]
sendTwitterRequest:request
completion:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
if (data) {
// handle the response data e.g.
NSError *jsonError;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:0
error:&jsonError];
for (NSDictionary *dataDict in json) {
NSString *text = [dataDict valueForKeyPath: #"text"];
dictionary = [NSDictionary dictionaryWithObjectsAndKeys:text,#"bodytext",nil];
[tweetObject addObject:dictionary];
}
}
else {
NSLog(#"Error: %#", connectionError);
}
}];
}
else {
NSLog(#"Error: %#", clientError);
}
} else {
NSLog(#"error: %#", [error localizedDescription]);
}
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return tweetObject.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
myCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell=[[myCell alloc]initWithStyle:
UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSDictionary *tmpDict = [self.tweetObject objectAtIndex:indexPath.row];
cell.txtLblOutput.text = [tmpDict objectForKey:text];
[tableView reloadData];
return cell;
}
#end
Here you can see the way my storyboard is put together and the references I am using
http://postimg.org/image/79w7pqmu3/
http://postimg.org/image/ixq9kabyz/
You should call [tableView reloadData]; in your request completion handler, after you've filled your array. Check if you receive any data. Does the array get filled with dictionary objects?
But mate, seriously, you need to read some good books about coding, your code really lacks understanding of what you're doing. Please, remove [tableView reloadData]; from the - ...cellForRowAtIndexPath:... method.

Access properties and methods from one class inside another class in Objective C

I am trying to build a class in Objective C that contain serve the web service and database methods for my application. In this class I want to call a web service and grab employee records and then load them into an SQL table for later use in a view.
I got this working when all the code as in the view, but in trying to make this new class (what I am calling GetEmployee) I am running into problems. I do not understand well how to access properties and methods from one class in another.
Here is my GetEmployee Class
#import <Foundation/Foundation.h>
#import "employee.h"
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#import "FMDatabasePool.h"
#import "FMDatabaseQueue.h"
#import "FMResultSet.h"
#import "Utility.h"
#interface GetEmployee : NSObject
{
NSMutableArray *employees;
}
#property (nonatomic, copy) NSString *databaseName;
#property (nonatomic, copy) NSString *databasePath;
- (void)updateEmployeeData;
- (void)callWebService;
- (void)fetchedData:(NSData *)responseData;
- (NSMutableArray *) getEmployees;
#end
implementation
#define kBgQueue dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define scoularDirectoryURL [NSURL URLWithString: #"https://XXXXXXXXX/mobile/mobilede.nsf/restServices.xsp/PeopleByName"]
#import "GetEmployee.h"
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#import "FMResultSet.h"
#implementation GetEmployee
- (id) init
{
if (self = [super init])
{
self.databaseName = #"employees.db";
}
return self;
}
#pragma
- (void)updateEmployeeData{
//Delete database if it exists and then copy fresh DB
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
self.databasePath = [documentDir stringByAppendingPathComponent:self.databaseName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success;
success = [fileManager fileExistsAtPath:self.databasePath];
if (success) {
[fileManager removeItemAtPath:self.databasePath error:nil];
}
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil];
//Call the web service
[self callWebService];
[self populateDatabase];
}
- (void) callWebService {
dispatch_sync(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:
scoularDirectoryURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData: responseData options: NSJSONReadingMutableContainers error: &error];
id jsonObject = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
employees = [[NSMutableArray alloc] init];
if (!jsonArray) {
} else {
for (jsonObject in jsonArray){
employee *thisEmployee = [employee new];
thisEmployee.fullName = [jsonObject objectForKey:#"$13"];
thisEmployee.ste = [jsonObject objectForKey:#"state"];
thisEmployee.city = [jsonObject objectForKey:#"city"];
[employees addObject:thisEmployee];
}
}
}
-(void) populateDatabase {
////Call the web service and populate the db
//dispatch_sync(kBgQueue, ^{
// NSData* data = [NSData dataWithContentsOfURL:
// scoularDirectoryURL];
// [self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
//});
//Populate the db
FMDatabase *db = [FMDatabase databaseWithPath:[Utility getDatabasePath]];
[db open];
for (employee *thisemployee in employees) {
BOOL success = [db executeUpdate:#"INSERT INTO employees (fullname,city,state) VALUES (?,?,?);",thisemployee.fullName,thisemployee.city,thisemployee.ste, nil];
if (success) {} // Only to remove success error
}
[db close];
}
- (NSMutableArray *) getEmployees
{
//NSMutableArray *employees = [[NSMutableArray alloc] init];
employees = [[NSMutableArray alloc] init];
FMDatabase *db = [FMDatabase databaseWithPath:[Utility getDatabasePath]];
[db open];
FMResultSet *results = [db executeQuery:#"SELECT * FROM employees"];
while([results next])
{
employee *thisEmployee = [employee new];
thisEmployee.fullName = [results stringForColumn:#"fullname"];
thisEmployee.city = [results stringForColumn:#"city"];
thisEmployee.ste = [results stringForColumn:#"state"];
[employees addObject:thisEmployee];
}
[db close];
return employees;
}
#end
And here is the MasterViewController
header
#import <UIKit/UIKit.h>
#import "employee.h"
#import "FMDatabase.h"
#import "FMResultSet.h"
#import "FMDatabaseAdditions.h"
#import "Utility.h"
#import "GetEmployee.h"
#interface MasterViewController : UITableViewController
{
NSMutableArray *employees;
//GetEmployee *ScoularEmployees;
}
#end
implementation
#define kBgQueue dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define scoularDirectoryURL [NSURL URLWithString: #"https://xxxxxxxx/mobile/mobilede.nsf/restServices.xsp/PeopleByName"]
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "employee.h"
#import "GetEmployee.h"
#interface MasterViewController () {
NSMutableArray *_objects;
}
#property(strong, nonatomic) GetEmployee *ScoularEmployees;
#end
#implementation MasterViewController
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//GetEmployee *ScoularEmployees = [[GetEmployee alloc] init];
[self.ScoularEmployees init];
//[self.ScoularEmployees init];
//_ScoularEmployees = [[GetEmployee alloc] init];
//[_ScoularEmployees getEmployees];
//GetEmployee *ScoularEmployees = [[GetEmployee alloc] init];
//GetEmployee *thisEmployeeData = [[GetEmployee alloc] init];
//[self.ScoularEmployees updateEmployeeData];
//[self.ScoularEmployees getEmployees];
//[ScoularEmployees updateEmployeeData];
//[ScoularEmployees getEmployees];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return employees.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *fullName = [[employees objectAtIndex:indexPath.row] valueForKey:#"fullName"];
cell.textLabel.text = fullName;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
employee *dtlEmployee = [employees objectAtIndex:indexPath.row];
[[segue destinationViewController] setDetailItem:dtlEmployee];
}
}
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData: responseData options: NSJSONReadingMutableContainers error: &error];
id jsonObject = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
//employees = [[NSMutableArray alloc] init];
if (!jsonArray) {
} else {
//NSMutableArray *employees = [[NSMutableArray alloc ]init];
for (jsonObject in jsonArray){
employee *thisEmployee = [employee new];
thisEmployee.fullName = [jsonObject objectForKey:#"$13"];
thisEmployee.ste = [jsonObject objectForKey:#"state"];
thisEmployee.city = [jsonObject objectForKey:#"city"];
[employees addObject:thisEmployee];
}
}
}
//-(NSMutableArray *) getEmployees
//{
//NSMutableArray *employees = [[NSMutableArray alloc] init];
//employees = [[NSMutableArray alloc] init];
// FMDatabase *db = [FMDatabase databaseWithPath:[Utility getDatabasePath]];
// [db open];
// FMResultSet *results = [db executeQuery:#"SELECT * FROM employees"];
//
// while([results next])
// {
// employee *thisEmployee = [employee new];
// thisEmployee.fullName = [results stringForColumn:#"fullname"];
// thisEmployee.city = [results stringForColumn:#"city"];
// thisEmployee.ste = [results stringForColumn:#"state"];
// //[employees addObject:thisEmployee];
// }
//
// [db close];
//
// return employees;
// return true;
//}
#end
Any help would be greatly appreciated.
I thought it was clear but I can see it is not. In the view class I want to be able to load an NSMutableArray called *employees that comes from the SQLLite database and out them on the screen. I have tried to centralize the code for data access in the GetEmployee class. Everything in that class deals with the data - web service, load the data to the database, and getting the data out of the database as well. So in that Class I have a method "getEmployees" that gets data from the db and loads it into that NSMutableArry. So here is the problem, in the class I cannot get access to the methods or properties in GetEmpployee. That is my question.
Without reading through all the code you've posted...
For using a Class method, the syntax is:
[ClassName methodName];
[ClassName anotherMethod:withArguments];
Methods that are called using this syntax will look like this in the corresponding .h file:
+(void)methodName;
+(void)anotherMethod:(NSNumber*)number;
For using an instance method, the syntax is:
ClassName myObj = [[ClassName alloc] init];
[myObj someMethod];
[myObj someOtherMethod:withArguments];
Methods that are called using this syntax will look like this in the corresponding .h file:
-(void)someMethod;
-(void)someOtherMethod:(NSString*)parameter;

Error when swipe to delete a table cell

I'm trying to delete a row when user swipes. I got this error driving me crazy. I've spent last three hours trying to figure out why. But, I have got no clue so far.
Here is my code to accomplish that.
in .h
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface FollowersTableViewController : UITableViewController
#property (nonatomic,strong)NSMutableArray *arrayWithUser ;
#end
and in .m i have this code .
#import "FollowersTableViewController.h"
#implementation FollowersTableViewController
#synthesize arrayWithUser ;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
NSDictionary *dicUrlList= [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Urls" ofType:#"plist"]];
NSString *baseURl = [dicUrlList objectForKey:#"urlWithUser"];
baseURl = [baseURl stringByAppendingFormat:#"getfollowers"];
NSURL *urlToGetFollowers = [NSURL URLWithString:baseURl];
NSURLRequest *request = [NSURLRequest requestWithURL:urlToGetFollowers];
NSError *error = nil ;
NSURLResponse *response = nil ;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arrayWithUser count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"Cell";
CustomCell *customCell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (customCell == nil)
{
customCell = [[CustomCell alloc] initWithFrame:CGRectMake(0, 0, 320, 50)] ;
}
NSDictionary *dicWithUser = [arrayWithUser objectAtIndex:indexPath.row];
NSString *photoUrl = [dicWithUser objectForKey:#"profilePhotoUrl"];
if(![photoUrl isEqualToString:#""])
[customCell.thumbnail setImageWithURL:[dicWithUser objectForKey:#"profilePhotoUrl"] placeholderImage:[UIImage imageNamed:#"placeholder.png"] ];
else
{
[customCell.thumbnail setImage:[UIImage imageNamed:#"placeholder.png"]];
}
customCell.titleLabel.text = [dicWithUser objectForKey:#"username"];
UIButton *buttonFollow = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[buttonFollow setTitle:#"Follow" forState:UIControlStateNormal];
CGRect frame = buttonFollow.frame ;
frame = CGRectMake(200, 10, 60, 30);
buttonFollow.frame = frame ;
buttonFollow.tag = indexPath.row ;
[buttonFollow addTarget:self action:#selector(followButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
customCell.accessoryView = buttonFollow ;
return customCell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60 ;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[arrayWithUser removeObjectAtIndex:indexPath.row];
}
}
So far,I'm able to see delete button, but when i pressed it gives me this error
[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object.
Since I've already used NSMutableArray, I've no idea, why I'm getting this error?
I've already try to clean project. It didn't make any difference.
Your Json call returning an NSArray. You can go to create a mutableCopy - so you're will be able to use the "removeAtIndex.." method.
NSArray *rData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
arrayWithUser = [rData mutableCopy];
The assignment to arrayWithUser from the JSON call is returning an NSArray not an NSMutableArray in viewDidLoad. Fix that.
Actually, your array(arrayWithUser) is strongly pointing to the array return by the JSONObjectWithData, as you don't have the ownership of the returned array, you can't remove its object.
You better do one thing ,take ownership of that array.
arrayWithUser = [[NSMutableArray alloc]arrayByAddingObjectsFromArray:[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]];
Just replace below line
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
with
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
From Apple's documentation:
NSJSONReadingMutableContainers: Specifies that arrays and dictionaries are created as mutable objects.
NSJSONReadingMutableLeaves: Specifies that leaf strings in the JSON object graph are created as instances of NSMutableString.
You used in viwDidLoad
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
Lets try like this
NSMutableArray *userMutarr = [NSMutableArray alloc]initWithCapacity:3];
self.arrayWithUser = userMutarr;
[userMutarr release];
Then
self.arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];