I have an SQLite database implemented in my xcode project. i want to view all name from database into tableview but getting an error as
NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index
9223372036854775807 beyond bounds [0 .. 13]'
#interface DisplayViewController ()
#property (nonatomic, strong) DBManager *dbManager;
#property (nonatomic, strong) NSArray *arrPeopleInfo;
#end
#implementation DisplayViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.mytableview.delegate = self;
self.mytableview.dataSource = self;
NSString *docsDir;
NSArray *dirPaths;
//Get the directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
self.dbManager = [[DBManager alloc] initWithDatabaseFilename:#"IApp.db"]; //Build the path to keep the database
// _databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:#"IApp.db"]];
// [self getcount];
[self loadData];
// [self getcount];
// Do any additional setup after loading the view.
}
- (void)loadData {
// Form the query.
NSString *query = #"select * from iApp";
if (self.arrPeopleInfo != nil) {
self.arrPeopleInfo = nil;
}
self.arrPeopleInfo = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
[self.mytableview reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.arrPeopleInfo.count;
// return [arri count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"idCellRecord" forIndexPath:indexPath];
NSInteger indexOfname = [self.dbManager.arrColumnNames indexOfObject:#"firstname"];
NSInteger indexOffname = [self.dbManager.arrColumnNames indexOfObject:#"lastname"];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", [[self.arrPeopleInfo objectAtIndex:indexPath.row] objectAtIndex:indexOfname], [[self.arrPeopleInfo objectAtIndex:indexPath.row] objectAtIndex:indexOffname]];
return cell;
}
When you search for an item in something, Cocoa returns NSNotFound for the index, if the method cannot find the item. This applies for -indexOfObject:, too. NSNotFound is a big integral number (INT_MAX) as you can see in the title of your Q.
Therefore
NSInteger indexOfname = [self.dbManager.arrColumnNames indexOfObject:#"firstname"];
will be NSNotFound, if #"firstName" is not found in the receiver. Please check, whether you have such a key. Typo? Camel case? firstNams?
If you do not know the keys at compile time you have to check for it, as #Inder told you:
if(indexOfname==NSNotFound)
// The object is not present
BTW: You should really recheck your naming. It does not follow the Cocoa naming conventions.
You can prevent this by using a very simple checking.
if(indexOfname < [self.dbManager.arrColumnNames count] && indexOffname < [self.dbManager.arrColumnNames count]) {
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", [[self.arrPeopleInfo objectAtIndex:indexPath.row] objectAtIndex:indexOfname], [[self.arrPeopleInfo objectAtIndex:indexPath.row] objectAtIndex:indexOffname]];
}
else {
cell.textLabel.text = #""; // or what ever you want to do
}
Please check whether indexOfname or indexOffname is equal to NSNotFound
NSInteger indexOfname = [self.dbManager.arrColumnNames indexOfObject:#"firstname"];
NSInteger indexOffname = [self.dbManager.arrColumnNames indexOfObject:#"lastname"];
if (indexOfname == NSNotFound) {
//Then don't use this index
}
if (indexOffname == NSNotFound) {
//Then don't use this index
}
Actually you have successfully fetched all record from Database. so left part is how to shown in UITableViewCell. modified cellForRowAtIndexPath as per below code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"idCellRecord" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", [[self.arrPeopleInfo objectAtIndex:indexPath.row] valeuForKey:#"firstname"], [[self.arrPeopleInfo objectAtIndex:indexPath.row] valueForKey:#"lastname"]];
return cell;
}
Related
The top 3 cells in my tableview have a label that says the word 'Squirrels'. Is there a way to make it so that if a UILabel says 'Squirrels' in more than one cell in my table, to only show the first cell of the three?
E.g. if UILabel userName in tableviewCell is equal to #"Squirrels", only show one table
view cell in the table that contains Squirrels in the UILabel
Hope this makes sense. Thanks in advance!
EDIT: I've successfully retrieved the first array containing more than one common 'name' value (see edit to code below). That said, when I try and display these values (firstFoundObject) in my tableview I get the following crash error:
-[__NSDictionaryI objectAtIndex:]: unrecognized selector sent to instance 0x1c01a5a20 2017-10-03 23:01:51.728128-0700
pawswap[623:85420] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSDictionaryI
objectAtIndex:]: unrecognized selector sent to instance 0x1c01a5a20'
ViewController.m
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *nodeTitle = self.messages[0][#"name"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", nodeTitle];
NSArray *filteredArray = [self.messages filteredArrayUsingPredicate:predicate];
id firstFoundObject = nil;
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil;
NSMutableArray *firstObjects = firstFoundObject;
return [firstObjects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *nodeTitle = self.messages[0][#"name"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", nodeTitle];
NSArray *filteredArray = [self.messages filteredArrayUsingPredicate:predicate];
id firstFoundObject = nil;
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil;
NSMutableArray *firstObjects = firstFoundObject;
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *receivedSubjectLine = [firstObjects objectAtIndex:indexPath.row];
NSString *messageSubject = [receivedSubjectLine objectForKey:#"node_title"];
[cell.subjectLine setText:messageSubject];
NSDictionary *fromUser = [firstObjects objectAtIndex:indexPath.row];
NSString *userName = [fromUser objectForKey:#"name"];
[cell.senderName setText:userName];
NSDictionary *receivedBody = [firstObjects objectAtIndex:indexPath.row];
NSString *messageBody = [receivedBody objectForKey:#"body"];
[cell.fullMessage setText:messageBody];
NSDictionary *messageReceived = [firstObjects objectAtIndex:indexPath.row];
NSString *timeReceived = [messageReceived objectForKey:#"published at"];
NSLog(#"Message Received at %#", timeReceived);
[cell.receivedStamp setText:timeReceived];
return cell;
}
PREVIOUS
ViewController.m
#pragma mark - Table view data source
- (int)numberOfSectionsInTableView: (UITableView *)tableview
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *receivedSubjectLine = [self.messages objectAtIndex:indexPath.row];
NSString *messageSubject = [receivedSubjectLine objectForKey:#"node_title"];
[cell.subjectLine setText:messageSubject];
NSDictionary *fromUser = [self.messages objectAtIndex:indexPath.row];
NSString *userName = [fromUser objectForKey:#"name"];
[cell.senderName setText:userName];
NSDictionary *receivedBody = [self.messages objectAtIndex:indexPath.row];
NSString *messageBody = [receivedBody objectForKey:#"body"];
[cell.fullMessage setText:messageBody];
NSDictionary *messageReceived = [self.messages objectAtIndex:indexPath.row];
NSString *timeReceived = [messageReceived objectForKey:#"published at"];
[cell.receivedStamp setText:timeReceived];
return cell;
}
Basically the problem you are getting is due to firstObject is of type Dictionary and you are type casting it to NSMutableArray. Please check below line:
id firstFoundObject = nil; firstFoundObject = filteredArray.count > 0
? filteredArray.firstObject : nil;
If you see you have filteredArray.firstObject as Dictionary in your application which you capture in firstFoundObject but later you are making it NSMutableArray type here:
NSMutableArray *firstObjects = firstFoundObject;
And later when you try to get here, it crashes
NSDictionary *receivedSubjectLine = [firstObjects
objectAtIndex:indexPath.row];
The correct - basic - version of your code should look like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
[cell.subjectLine setText:[self.recvMessage objectForKey:#"node_title"]];
[cell.senderName setText:[self.recvMessage objectForKey:#"name"]];
[cell.fullMessage setText:[self.recvMessage objectForKey:#"body"]];
[cell.receivedStamp setText:[self.recvMessage objectForKey:#"published at"]];
return cell;
}
Though it is not optimised but still it can do work for you.
COUNT ISSUE:
NSMutableDictionary *firstObjects = firstFoundObject;
return [firstObjects count];
In your code above you have inside the numberOfRowsInSection since you have firstFoundObject as dictionary so when you call [firstObjects count] which is a valid call and it returns the number of key in the dictionary.
You have modify it like :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
NSInteger rowCount = filteredArray.count;
self.recvMessage = rowCount? filteredArray.firstObject: nil;
return rowCount? 1: 0;
}
and you have new data which actually stores the filtered object.
#property (nonatomic) NSDictionary *recvMessage;
Hope this helps.
Yes you can do it easily,
You will do it before run tableView,
for example :
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary* NameDictionary=[[NSMutableDictionary alloc] init];
NSString* PreviousName;
int oneTime=0;
for(int i=0;i<[self.messages count];i++){
NSDictionary *fromUser = [self.messages objectAtIndex: i];
NSString *userName = [fromUser objectForKey:#"name"];
if(oneTime==0)
{
PreviousName=userName;
[NameDictionary addObject:[self.messages objectAtIndex: i]];
oneTime=1;
}
if(oneTime!=0)
{
if([PreviousName isEqualToString: userName])
{
}
else{
[NameDictionary addObject:[self.messages objectAtIndex: i]];
}
PreviousName=userName;
}
}
}
When you ask to filter out cells with a senderName property equal to #"Squirrels", you're effectively asking to change your datasource after it has been set. This will cause problems in your numberOfRowsInSection method, which will return more rows than you need if any filtering takes place after the datasource is set.
As one of the comments to your answer suggests, "make a secondary array which contains unique elements of self.messages and work with this array." The array that makes up the datasource of the tableview should require no filtering. The tableview should just be able to present it.
If I had enough reputation to comment on the above answer, I would say that you're right that it doesn't work because self.messages doesn't change. Instead of collecting the "non-duplicate" objects in NameDictionary, consider collecting them in an NSMutableArray. This new, filtered array should be the datasource for your array. You may want to filter this array outside of this ViewController so that once the array arrives at this view controller it can just be assigned to self.messages.
If you're looking to exclude all duplicates, as opposed to just duplicates that appear next to each other, consider this answer.
I'm sorting my array by last name alphabetically. I'd like to separate this into sections with the appropriate header above each section (A, B, C, etc.).
Here's what I've tried below:
// Here is where I refresh the data and sort it based on last name
- (void)refreshData {
[[PCMSSessionManager sharedSession] refreshPCMSDataWithCompletion:^(BOOL success, NSString *errorMessage, id resultObject) {
if (success) {
NSLog(#"yay!");
self.membersArray = [[PCMSSessionManager sharedSession] memberArr];
// Let's sort the array
self.sortedArray = [self.membersArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [(PCMSMember*)a lastName];
NSString *second = [(PCMSMember*)b lastName];
return [first compare:second];
}];
[self.tableView reloadData];
} else {
NSLog(#"boooo!!!!");
}
}];
}
- (NSDictionary *)indexedMembers
{
NSMutableDictionary *indexedContacts = [NSMutableDictionary new];
for (PCMSMember *member in self.sortedArray)
{
NSString *sortString = member.lastName;
NSString *sortLetter = [sortString substringToIndex:1];
/* see if that letter already exists as an index */
BOOL foundKey = NO;
for (NSString *key in [indexedContacts allKeys])
{
if ([key isEqualToString:sortLetter])
{
foundKey = YES;
}
}
NSMutableArray *valueArray;
if (foundKey)
{
valueArray = [((NSArray *)indexedContacts[sortLetter]) mutableCopy];
}
else
{
valueArray = [NSMutableArray new];
}
[valueArray addObject:member];
indexedContacts[sortLetter] = [valueArray copy];
}
return [indexedContacts copy];
}
// Here's my table data
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[[self indexedMembers] allKeys] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *indexedContacts = [self indexedMembers];
NSArray *myKeys = [indexedContacts allKeys];
NSString *key = myKeys[section];
return [((NSArray *)[self indexedMembers][key]) count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// Configure the cell...
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (self.isPhysician == YES) {
NSString *key = [[self indexedMembers] allKeys][indexPath.section];
PCMSMember *currentMember = ((NSArray *)[self indexedMembers][key])[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", currentMember.firstName, currentMember.lastName];
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[self indexedMembers] allKeys][section];
}
UPDATE:
This is getting me closer to what I want.
The data is loading, it's being grouped properly and the headers are showing.
But it's not in alphabetical order.
How can I improve this code to show alphabetically?
It's showing in alphabetical order in my console, just not in the app.
The NSMutableDictionary is unordered by definition. It is not the natural choice if you rely on the order of the stored objects. I suggest you to use NSMutableArray instead. To store the tableview data for each section you can use this mini class
#interface MembersWithSameInitial : NSObject
#property (strong) NSString* initial;
#property (strong) NSMutableArray<PCMSMember*>* members;
#end
#implementation MembersWithSameInitial
#end
After you have sorted the members, all the data for the tableview can be produced with this before tableView reload.
NSMutableArray<MembersWithSameInitial*>* groupedMembers = [[NSMutableArray alloc] init];
for (PCMSMember* member in sortedArray) {
NSString* inicial = [member.lastName substringToIndex:1];
MembersWithSameInitial* last = [groupedMembers lastObject];
if (last && [last.initial isEqualToString:inicial]) {
[last.members addObject:member];
} else {
MembersWithSameInitial* newGroup = [[MembersWithSameInitial alloc] init];
newGroup.initial = inicial;
newGroup.members = [[NSMutableArray alloc] initWithObjects:member, nil];
[groupedMembers addObject:newGroup];
}
}
Since the structure of groupedMembers fits to a grouped tableView, the dataSource methods will have trivial implementations. Assuming, that you have stored groupedMembers in a property.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.groupedMembers.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.groupedMembers[section].members.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//...
PCMSMember *currentMember = self.groupedMembers[indexPath.section].members[indexPath.row];
//...
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return groupedMembers[section].initial;
}
Suggestion:
Create two properties
#property NSMutableArray *keys; // for the letters in alphabetical order
#property NSMutableDictionary *indexedContacts; // same as your implementation.
In the method refreshData call the method to create the data source and then reload the table view on the main thread.
Actually you don't need the properties memberArray and sortedArray anymore. The sorted array is passed to the method to create the data source.
- (void)refreshData {
[[PCMSSessionManager sharedSession] refreshPCMSDataWithCompletion:^(BOOL success, NSString *errorMessage, id resultObject) {
if (success) {
NSLog(#"yay!");
self.membersArray = [[PCMSSessionManager sharedSession] memberArr];
// Let's sort the array
NSArray *sortedArray = [self.membersArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [(PCMSMember*)a lastName];
NSString *second = [(PCMSMember*)b lastName];
return [first compare:second];
}];
[self indexMembers:sortedArray];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
} else {
NSLog(#"boooo!!!!");
}
}];
}
The method indexMembers initializes the properties keys and indexedContacts and creates the data source.
- (void)indexMembers:(NSArray *)sortedMembers
{
self.keys = [[NSMutableArray alloc] init];
self.indexedContacts = [[NSMutableDictionary alloc] init];
for (PCMSMember *member in sortedMembers)
{
NSString *sortString = member.lastName;
NSString *sortLetter = [sortString substringToIndex:1];
/* see if that letter already exists as an index */
NSArray *keyArray = self.indexedContacts[sortLetter];
NSMutableArray *valueArray;
if (keyArray) {
// array for key exists, use it
valueArray = [keyArray mutableCopy];
} else {
// array for key does not exist, create a new one
valueArray = [NSMutableArray new];
// and add the letter to keys
[self.keys addObject:sortLetter];
}
[valueArray addObject:member];
self.indexedContacts[sortLetter] = [valueArray copy];
}
}
numberOfSectionsInTableView returns the number of keys
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.keys.count;
}
numberOfRowsInSection gets the appropriate array for the given section and returns the number of items.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *letter = self.keys[section];
NSArray *memberArray = self.indexedContacts[letter];
return memberArray.count;
}
In cellForRowAtIndexPath use the method dequeueReusableCellWithIdentifier: forIndexPath: to get always a valid cell. Then like in numberOfRowsInSection get the actual member array and populate the label.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (self.isPhysician == YES) {
NSString *letter = self.keys[indexPath.section];
NSArray *memberArray = self.indexedContacts[letter];
PCMSMember *currentMember = memberArray[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", currentMember.firstName, currentMember.lastName];
}
return cell;
}
titleForHeaderInSection simply returns the letter for the section
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.keys[section];
}
You're calling indexedMembers too much. This is very expensive.
I couldn't test the code, maybe there is a self or something else missing but you get an impression of the workflow.
right now I'm getting and error regarding a table view cell trying to read data from an object. I am hitting a database, storing all the rows into an NSMUtable Array as object which seems to be working fine. But when I want the table view to read that array, I keep getting 'null'. Any help would be greatly appreciated.
ERROR
-[AttendeeData isEqualToString:]: unrecognized selector sent to instance 0x751ca80
2013-03-16 11:40:52.499 ExpoRequestLite[39716:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException',
#interface DashLandingViewController ()
#end
#implementation DashLandingViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self){
// Custom initialization
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
entries = [[NSMutableArray alloc]init];
_attendeeDataToPush = [[AttendeeData alloc]init];
[self openDB];
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM data"];
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)== SQLITE_OK) {
while(sqlite3_step(statement) == SQLITE_ROW){
NSLog(#"got all attendees");
NSString *firstName = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
_attendeeDataToPush.firstNameValue = firstName;
[entries addObject:_attendeeDataToPush];
NSLog(#"array has %#", [[entries objectAtIndex:0] firstNameValue]);
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [entries count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSLog(#"selected firstname is %#", [[entries objectAtIndex:0] firstNameValue]);
cell.textLabel.text = [entries objectAtIndex:indexPath.row];
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
#end
Error suggests that you have error somewhere else in your code, post your complete code. From your error it seems that you are calling isEqualToString: on object which is not string type. Your code does not show where you getting the error. For Using isEqualToString: both objects should be of NSString type. If you are comparing object with string then use isEqual: instead.
Errors may happening here
NSLog(#"selected firstname is %#", [[entries objectAtIndex:0] firstNameValue]);
cell.textLabel.text = [entries objectAtIndex:indexPath.row];
Modify these lines to,
if([entries count] > indexPath.row){
AttendeeData *attendeeData = [entries objectAtIndex:indexPath.row];
NSLog(#"selected firstname is %#", attendeeData.firstNameValue);
cell.textLabel.text = attendeeData.firstNameValue;
}
I'm making a note taking app for the iPad, and it lets the user draw lines, and right now, it can save the pages of the notebook by saving each page as a PNG in the documents directory. Here's the code I have to save the images:
- (IBAction)saveImage:(id)sender {
UIImage *saveImage = drawImage.image;
if (saveImage != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: #"%#-%d.png", #"image", numberOfPages] ];
NSData* data = UIImagePNGRepresentation(saveImage);
[data writeToFile:path atomically:YES];
}
}
Just as a side note, numberOfPages is an int that is set to add 1 each time a "new page" button is pressed, this way, each image is named "image1", "image2", etc.
So my question is: How would I set up a UITable so the user can see a list of all the pages they've made.
Thanks so much for your time,
Karl
Each time you make a new page, add a string with the image's name to an array. Then, iterate through the array to populate a UITableView. When the user selects a cell, open the file with that name.
#import "RootViewController.h"
#implementation RootViewController
#synthesize keys, names;
AppDelegate *appD;
- (void)viewDidLoad
{
[super viewDidLoad];
appD = (AppDelegate *)[[UIApplication sharedApplication] delegate];
names = appD.data;
NSArray *array = [[names allKeys] sortedArrayUsingSelector:#selector(compare:)];
keys = array;
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return [keys count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = indexPath.section;
NSUInteger row = indexPath.row;
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [appD.data objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
key = [key substringFromIndex:2];
return key;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = indexPath.section;
NSUInteger row = indexPath.row;
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [appD.data objectForKey:key];
appD.theInfo.primary = [nameSection objectAtIndex:row];
[self performSegueWithIdentifier:#"secondarySegue" sender:self];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
This is for a table in a navigation controller that populates itself from a .plist and moves to another table when a cell is clicked. The tableview is connected to the view controller with delegate and datasource outlets.
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];