Parse Event Title from Event Kit - ios

So, I would like to read in my array of events from a calendar I am subscribed to.
The events all have a similar format, for example with two modules, 'Meaning of Life' and 'Running long distances':
Talk: Meaning of Life
Talk: Running long distances
Talk: Meaning of Life
Talk: Meaning of Life
Talk: Running long distances
I would like to be able to use something like
[[event.title componentsSeparatedByString:#"Talk: "] objectAtIndex:i];
So that in my table view I can have a 'Meaning of life' cell and a 'Running long distances' one. The idea would then be to select one and you could see all the 'Talks' for that module. There are other categories too like 'Workshops' and 'Practicals'.
Currently my code to just display all the events is as follows (ignoring the getting events of selected calendar and producing an array titled arrEvents)
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TableIDCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"TableIDCell"];
}
// Get each single event.
EKEvent *event = [self.arrEvents objectAtIndex:indexPath.row];
// Set its title to the cell's text label.
cell.textLabel.text = event.title;
// Get the event start date as a string value.
NSString *startDateString = [self.appDelegate.eventManager getStringFromDate:event.startDate];
// Get the event end date as a string value.
NSString *endDateString = [self.appDelegate.eventManager getStringFromDate:event.endDate];
// Add the start and end date strings to the detail text label.
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", startDateString, endDateString];
if (indexPath.row%2 == 0) {
UIColor *altCellColor = [UIColor colorWithWhite:0.7 alpha:0.1];
cell.backgroundColor = altCellColor;
}
return cell;
}
Thanks for taking the time to read :)

I sorted it in the end by modifying the arrEvents in the class where it is generated. I was able to check if it contained string "Talk: " and them remove that bit and also check if arrEvents already contained a title and then not to add duplicates.

Related

How to properly loop through cells of a table view and add the objects from the array to a new array

Ok so I have very little experience with programming so please be patient. Let me explain further...I have a player class that has different properties. In the table view I number first name and last name of the player. I want to loop through each cell, and take the number first name and last name and add it to a new array. I don't want to be just add them as strings. I want to put them into a pickerview after ward. I have an dictionary that matches each number to a player ID. How would i do all of this? I have a loop that goes through tableviewcells which is like this
for (_tableViewCell in self.homePlayers.visibleCells)
{
if (_tableViewCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
[_homeConfirmedPlayersArray addObject:[NSString stringWithFormat:#"%d %# %#",_homePlayer.number,_homePlayer.firstName,_homePlayer.lastName]];
}
}
homePlayers is the tableView that I am looping through. The problem is that it does go through each cell but it only takes the data from the last cell and adds it the new array once for each cell. I end up with 8 objects of the number first name and last name.
I set up the homePlauer object in cell for row at index path like this...
if ([tableView isEqual:self->_homePlayers])
{
static NSString *cellIdentifier = #"cell";
//Step 1: Check to see if we can reuse cell from a row that is now off the screen.
_tableViewCell = [_homePlayers dequeueReusableCellWithIdentifier:cellIdentifier];
//Step 2: If no reusable cells create a new one
if (_tableViewCell == nil)
{
_tableViewCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
//Add detail view accessory
_tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
//Step 3: Set up cell text
_homePlayer = _homePlayersArray[indexPath.row];
_tableViewCell.textLabel.text = [NSString stringWithFormat:#"%d %# %#",_homePlayer.number,_homePlayer.firstName,_homePlayer.lastName];
//Step 4: Return the cell
return _tableViewCell;
}
If you need anymore information please ask. Thanks for the answers ahead of time!
It looks like you did a problem a lot of new programmer do, globalize everything. _homePlayer looks like it should be a local variable. What I assume is happening is when the UITableView is populating itself by calling tableView:cellForRowAtIndexPath:, the last cell that will be generated will set the global _homePlayer. Then when you other loop function gets called, _homePlayer will have already been set, and you also never change it in your loop function. That's why you get the same 8 objects. Here's how to fix it:
Make step 3 this:
id homePlayer = _homePlayersArray[indexPath.row];
tableViewCell.textLabel.text = [NSString stringWithFormat:#"%d %# %#", homePlayer.number, homePlayer.firstName, homePlayer.lastName];
You should replace 'id' with the homePlayer type so the compiler will assist you with auto completion.
I think you mentioned it was a NSDictionary, so replace id with NSDictionary *.
For your loop function do this: (comments for explanation)
// create a new and empty array
// (your local array will forever fill up with repeated objects unless emptied somewhere)
NSMutableArray *homeConfirmedPlayersArray = [[NSMutableArray alloc] init];
// loop through all indexpaths for the visible cells
for (NSIndexPath *indexPath in [self.homePlayers indexPathsForVisibleRows]){
// get the tablecell, only to check the accessory type
UITableViewCell *cell = [self.homePlayers cellForRowAtIndexPath:indexPath];
// I don't think this is necessary, especially if every cell has a checkmark
if (cell.accessoryType == UITableViewCellAccessoryCheckmark){
// get the record from the home players array
NSDictionary *homePlayer = _homePlayersArray[indexPath.row];
// add to the copy
[homeConfirmedPlayersArray addObject:[NSString stringWithFormat:#"%d %# %#",homePlayer.number,homePlayer.firstName,homePlayer.lastName]];
}
}
Remember to only use global variables only when you need them to be global.

observables and the UItableview visible cells

I am writing an IOS chat app.
I have a tableview where each cell contains a textbox, upon loading each cell I subscribe to a chat channel on pubnub.com. I have an observable in the viewdidLoad watching for incoming messages. The object receieved from the observable contains the channel name and the message text and date.
I want to display messages to their appropriate cells.
I'm not sure where to capture a fully loaded cell when its in view and subscribe to the channel. Then in the observable how do I compare the channel name to the cell currently in view on the screen?
I tried the isVisible but I'm getting more than whats visible on the screen. The thing is I want to only show messages to cells that are currenty in view, kind of how vine starts to playa video when the user has stopped on that cell even if they dont click it..
See code below
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
self.messages = [NSMutableDictionary dictionary];
self.configuration = [PNConfiguration defaultConfiguration];
[self load_DEMO_DATA];
[self setClient];
[self connectToServer];
//Observable
[[PNObservationCenter defaultCenter] addMessageReceiveObserver:self
withBlock:^(PNMessage *message) {
NSDateFormatter *dateFormatter = [NSDateFormatter new];
dateFormatter.dateFormat = #"HH:mm:ss MM/dd/yy";
PNChannel *channel = message.channel;
NSString *messages = [self.messages valueForKey:channel.name];
if (messages == nil) {messages = #"";}
messages = [messages stringByAppendingFormat:#"<%#> %#\n",[dateFormatter stringFromDate:message.receiveDate.date],message.message];
//Get TextBox & Set Caption
UITextView *caption = (UITextView *)[[(UITableViewCell *)[(UITableView *)self.tableView cellForRowAtIndexPath:CurrentIndexPath] contentView] viewWithTag:105];
caption.text = [NSString stringWithFormat:#"%#%#", caption.text, messages];
[caption scrollRangeToVisible:NSMakeRange([caption.text length], 0)];
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TimelinePostCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
// Configure the cell...
NSDictionary *post = [posts objectAtIndex:indexPath.item];
NSDictionary *user = [post objectForKey:#"user"];
//Set Current Channel
self.currentChannel = [PNChannel channelWithName:[post objectForKey:#"channelName"] shouldObservePresence:YES];
//Subscribe to Chat
[self subscribeToChannel:self.currentChannel.name];
self.currentPost = post;
//Get Channel History
[self ChannelHistory];
return cell;
}
Well, first of all, -tableView:cellForRowAtIndexPath: shouldn't be used to initiate any time consuming operations. To keep high performance, you should return prepared UITableViewCell from that method less then in 160ms or you will see "lag". This method will be called few times right after table has been shown (as many as you have cells with values).
You should use –scrollViewDidEndDragging:willDecelerate: (with decelerate NO) and –scrollViewDidEndDecelerating: as appropriate place and time when you should initiate subscriptions to the channel and any other manipulation with PubNub client.
You can subscribe on all channels at once - it will be less network overhead than subscribing for every single channel one-by-one. If you want to preserve resources and keep pricing low by keeping client subscribed on few channels, than you should use same methods to unsubscribe from previous channels (same as were suggested to detect current cell and store current channel and so on).
Also just suggestion about how you feed cell with model: move model processing inside custom cell class (there is no reason for controller to know something about structure of cell's views and which data should be shown there).

How to skip a specific string when populating my UITableView

I am populating a tableview from data that is received from a server. The data is a list of user activities within a given timeframe. One such activity is "Login". I do not wish to populate my tableview with this string but I'm not sure how to skip it when populating my tableview.
Here is how I populate the cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
#try{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *action = [object valueForKey:#"theActionName"];
if ([action isEqualtoString:#"Login"]) {
return cell;
}
return cell;
}#catch (NSException *ex) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
}
As you can see I tried using return cell but as you probably know it gives me a blank cell when the table is displayed. I'm sure there is a simple line of code for this but I came up blank with the search terms I used. Could someone please enlighten me! Thanks!
P.S. you may be thinking I am not putting anything in any of the cells but I pulled out a bunch of code to keep this short.
UPDATE:
Thanks for the heads up on "isEqualtoString:" Everything worked fine with "isEqual" but I changed it given that I received so many suggestions to do so. But this is not what I am asking.
To be more clear if I had an array containing the terms: view, view, login, view. When my tableview was populated I would have 4 cells that said; view, view, login, view. I simply want to ignore the term login so that I would have 3 cells that all said view. Thanks!
There can be many way to do this.
I Belive that UITabelView should display what its datasource (here datasource is self.fetchedResultsController) contains.
What you can do is create another NSArray from self.fetchedResultsController which does not contain this object.
Try this:
NSMutableArray *newSource = [[NSMutableArray alloc] init];
for(int i = 0; i < self.fetchedResultsController.count ; i++)
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *action = [object valueForKey:#"theActionName"];
if (![action isEqual:#"Login"])
{
[newSource addObject:action];
}
}
[tableView reloadData];
Now use newSource instead of self.fetchedResultsController
You might think that using one more array is not good. But believe it it is far easier than using the same array with condition. You don't have to worry about that condition when you perform some operation with your UITableView like remove object by using indexpath.
try using if ([action isEqualToString:#"Login"])
When you want to compare strings you need to use this isEqualToString .
Change this line
if ([action isEqualToString:#"Login"]) {
return cell;
}
You are using the wrong function to compare your input string and the given data variable.
They both are NSString objects so use :
if([action isEqualToString:#"Login"])
{
//enter your code here
}
#Ben : I am assuming that you have registered you cell through nib as you are using dequeueReusableCellWithIdentifier.
Make your tableview content as "Dynamic prototype" (You can see this in Attributes Inspector of table view) and change your table view cell style as custom (You can see this in Attributes Inspector of tableview cell).

Trying to load only certain entities into a table view

I have a data model with entity Customer. The Customer has attributes like name, address...etc. One of these attributes is a call back date. I want to load into the table only the Customers with call back date of today. below is the code I have to check to see if the dates are equal and then to create the cell. The problem is when the dates are not equal and it skips the creation of the cell. How do I skip that specific customer and move to the next one?
if(date==date2 && month==month2 && year==year2)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *string = [NSString stringWithFormat:#"%# %#", cust.firstName, cust.lastName];
cell.textLabel.text = string;
return cell;
}
return nil;
}
I'd take a different route altogether.
Rather than not showing anything in the cell, simply don't provided data for there to even be a cell. You mention that you're using models so I assume you're using core data?
If so, then change your predicate when you fetch your models to ignore all objects that don't meet your criteria. Then you can just show every object in your table as you know that there aren't any you don't want.
Alternatively, fetch everything (if perhaps you're not using core data) then apply a predicate to the array of data you're using and filter it out that way.

UITextfield in UITableview with Calendar value

I have a question about populating UITableViewCell with the selected value in calendar. So i have this tableview which is of course created when the view appears, and as i said i also i have this calendar view controller. The main idea is that users can select a date on the calendar, and after that that value should appear in the text field in tableview.
I've have a function that is returning the selected value from the calendars view controller to that other view controller, but after that i can't populate the UITextField with that value.
Any idea or previous similar experience?
Here is the code that is used in the calendar view controller
-(void)giveString:(NSString*)string{
GradesViewController *grades = [[GradesViewController alloc]init];
[grades getString:string];
NSLog(#"String : %#",string);}
and here is the class in that other view in which i want this string value from calendar in my textfield located in tableviewcell
-(void)getString:(NSString*)string{
stringDate = string;
NSLog(#"String: %#",stringDate);}
the both values appear in log...
You are never retaining "string" in [GradesViewController getString:string]
-(void)getString:(NSString*)string {
stringDate = string;
[stringDate retain];
NSLog(#"String: %#",stringDate);
}
Make sure it's released as well in order to ensure that garbage collection will clean it up.
you need to set the stringDate value in cellForRowAtIndexpath, if you are declared that textfield in your tableviewcell cellForRowAtIndexpath. If you are using custom tableviewcell, you need to pass that value to you custome tableView cell class, like how you are calling from CalendarViewController to other ViewController
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellId = #"cellId";
UITableViewCell *tableCell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (tableCell == nil) {
tableCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
UITextField *urlTxtFld = [[UITextField alloc] initWithFrame:CGRectMake(70, 10, 230, 120)];
urlTxtFld.backgroundColor = [UIColor clearColor];
urlTxtFld.text = stringDate // you need to set your text like this
urlTxtFld.autocorrectionType = UITextAutocorrectionTypeNo;
[qrCell addSubview:urlTxtView];
[urlTxtFld release];
}
}

Resources