I want to create a list of time zones.
But I got the following error at timeZone.abbreviation.
-[__NSCFString abbreviation]: unrecognized selector sent to instance 0x19cb80b0
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell...
NSTimeZone *timeZone = [[NSTimeZone knownTimeZoneNames] objectAtIndex:indexPath.row];
cell.textLabel.text = timeZone.abbreviation; // <- Error Here
cell.detailTextLabel.text = timeZone.description;
cell.accessoryType = (timeZone == self.timeZone)? UITableViewCellAccessoryCheckmark :UITableViewCellAccessoryNone;
return cell;
}
I tried to search on the internet but I cannot find the solution so far.
Please give me some advice.
Thanks in advance.
Try something like this:
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:[[NSTimeZone knownTimeZoneNames] objectAtIndex:indexPath.row]];
cell.textLabel.text = timeZone.abbreviation; // <- Error Here
cell.detailTextLabel.text = timeZone.description;
Your current code gets an array of NSStrings, not NSTimeZones. This should give you an NSTimeZone, and then you can get the abbreviation property on it.
as mentioned here: https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/NSTimeZone_Class/Reference/Reference.html#//apple_ref/occ/clm/NSTimeZone/knownTimeZoneNames
[NSTimeZone knownTimeZoneNames]
returns a list of String ids of the timezones - so your timezone object actually contains a NSString not a NSTimeZone object. So you have to do:
NSString *timeZoneID = [[NSTimeZone knownTimeZoneNames] objectAtIndex:indexPath.row];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:timeZoneID];
to get the real timezone object to call abbreviation on
Related
This question already has answers here:
Format String is not a literal string (potentially insecure) warning [duplicate]
(1 answer)
Warning : Format string is not a string literal (potentially insecure)
(1 answer)
Closed 8 years ago.
I'm creating a school app that displays the messages, users and the timestamp. I tried looking online for a fix to this but i couldn't find anything that I could understand. I'm new to programming and anything could help. I read somewhere that NSLog could help but I don't know how it's used. Please help!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"messagesCell";
MessageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
reversedMessages = [[messagesArray reverseObjectEnumerator] allObjects];
PFObject *tempObject = [reversedMessages objectAtIndex:indexPath.row];
cell.cellTitle.text = [tempObject objectForKey:#"content"];
cell.userName.text = [tempObject objectForKey:#"user"];
NSDate *createdAt = [tempObject createdAt];
NSDateFormatter *dateDisplay = [[NSDateFormatter alloc] init];
[dateDisplay setDateFormat:#"MMM, d h:mm a"];
**cell.timeStamp.text = [NSString stringWithFormat: [dateDisplay stringFromDate:createdAt]];**
return cell;
}
If you're using stringWithFormat, it expects a format string with %#'s being replaced by comma-separated parameters, like this:
[NSString stringWithFormat:#"This is param1: %#, and param2: %#", param1, param2];
If you're using a normal NSString, you want to simply do this:
cell.timeStamp.text = [dateDisplay stringFromDate:createdAt];
The alternative, which I want to doubly emphasize is just to contrast with the better way above and in this case is pointless, would be:
cell.timeStamp.text = [NSString stringWithFormat:#"%#", [dateDisplay stringFromDate:createdAt]];
I made a custom UITableViewCell and when I display it, i have this result (I'm running xcode 6 and iOS 8 beta 1 on an iPhone 5.)
http://imgur.com/2MyT0mF,Nx1o4bl#0
And when I rotate my device, then rotate back to portrait, everything becomes correct.
http://imgur.com/2MyT0mF,Nx1o4bl#1
Note that when I was using xcode 5 to compile my app, I had no problems.
Code used in cellForRowAtIndexPath:
BGTCoursCell1 *cell = (BGTCoursCell1 *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"BGTCoursCell1" owner:self options:nil];
cell = [nib objectAtIndex:0];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm"];
NSLocale *locale = [NSLocale currentLocale];
[dateFormatter setLocale:locale];
if (indexPath.section == 0)
{
BGTCours *cours = [[currentDay coursMatin] objectAtIndex:indexPath.row];
cell.matiereLabel.text = [cours matiere];
cell.salleLabel.text = [cours salle];
cell.heureLabel.text = [NSString stringWithFormat:#"De %# à %#", [dateFormatter stringFromDate:[cours beginDate]], [dateFormatter stringFromDate:[cours endDate]]];
}
else
{
BGTCours *cours = [[currentDay coursAprem] objectAtIndex:indexPath.row];
cell.matiereLabel.text = [cours matiere];
cell.salleLabel.text = [cours salle];
cell.heureLabel.text = [NSString stringWithFormat:#"De %# à %#", [dateFormatter stringFromDate:[cours beginDate]], [dateFormatter stringFromDate:[cours endDate]]];
}
return cell;
Thanks !
You need to return a CGFloat from the tableView:heightForRowAtIndexPath: . The error you are seeing will appear if you return a float from the same method:
//causes the bug
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//...
}
//fixes the bug
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return tableView.rowHeight; // whatever
}
This question has an accepted answer, but I have the same problem which was not fixed by the accepted answer which tells us to change float to CGFloat.
I found out that people who has code based on table's rowHeight may have this problem too. In iOS8 it is important to look at estimatedRowHeight not just rowHeight.
As I was using these variables in my programmatically generated UITableView, fixing those variables solved the problem.
I might be a bit late to the party but I've encountered exactly same problem with iOS 8 beta 2 and xCode 6 beta 2 today(26-June-2014), I see they still haven't fixed the bug.
There's also another bug with xCode 6 beta, that is my app can no request the GPS location properly - it simply won't ask for the permission. This is also solved by switching back to xCode 5. I think at the moment is more viable to use xCode 5 to build and test your app.
try reusing the cell, like, change:
BGTCoursCell1 *cell = (BGTCoursCell1 *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"BGTCoursCell1" owner:self options:nil];
cell = [nib objectAtIndex:0];
to
static NSString *CellIdentifier = #"Cell";
static NSString *CellNib = #"BGTCoursCell1";
BGTCoursCell1 *cell = (BGTCoursCell1 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if( cell == nil ) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = [nib objectAtIndex:0];
}
...
return cell;
i had a slightly similar problem and fixed it by using
cell.clipsToBounds = YES
I have read the other questions concerning multiple methods but still do not know how to fix my code. I would be grateful for help with this. I have put a * around the statement where the error occurs.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"eventCell";
EQCalendarCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[EQCalendarCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
cell.titleLabel.text = [[self.eventsList objectAtIndex:indexPath.row] title];
cell.locationLabel.text = [[self.eventsList objectAtIndex:indexPath.row] location];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat: #"dd-MM-yy HH:mm"];
NSString *startDateString = [df stringFromDate:[[self.eventsList
objectAtIndex:indexPath.row] startDate]];
cell.startDateLabel.text = startDateString;
NSString *endDateString = [df stringFromDate:[[self.eventsList
objectAtIndex:indexPath.row] endDate]];
cell.endDateLabel.text = endDateString;
return cell;
}
Thanking you in advance for your help.
Casting the result of retrieving the object from the self.eventsList collection should solve the problem. E.g.:
cell.locationLabel.text = [((MyClassName *)[self.eventsList objectAtIndex:indexPath.row]) location];
Replacing MyClassName with the name of the class in the collection.
You need to cast [self.eventsList objectAtIndex:indexPath.row] to the relevant type so that the compiler knows what data type your are dealing with.
Without seeing how your self.eventList list is populated it's not possible to tell you the solution exactly, but your line should be replaced with something like this (split into two lines for clarity, but you could use a cast instead of a variable to keep it on one line)
MyEventClass *event = [self.eventsList objectAtIndex:indexPath.row];
cell.locationLabel.text = [event location];
You need to cast EKEvent class. This will solve your problem...
EKEvent *event = [self.eventlist objectAtIndex:indexPath.row];
NSString *placeStr=[event location];
In one scenario, if the factory method that creates the object has return type "id" then the compiler will check the method signature in all the classes. If compiler find the same method signature in more than one class then it will raise the issue. So replace the return type "id" with "specific class name".
In my tableViewController there is a cellForRowAtIndex method which has three possible sources.
Search results from a search bar controller.
Collapsed sections from NSFetchedResultsController.
Expanded sections from NSFetchedResultsController.
At the first option there are no issues.
At the second option, the method creates a new Top Row to announce that the section is expandable. No issues at this option.
At the third option, the selected section expands its rows, but with the issue that the first row is not the expected row, but the new Top Row from the previous option.
Here you have both screenshots:
And that is the method code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
ToDoItem *toDoItem = nil;
//SEARCH RESULTS
if (tableView == self.searchDisplayController.searchResultsTableView)
{
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
NSLog(#"Configuring cell to show search results");
toDoItem = [self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem.todoName;
NSDate *fechaToDO = toDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
NSString *valorSomeDay = toDoItem.isSomeDay;
if ([valorSomeDay isEqualToString:#"issomeday"]){
cell.detailTextLabel.text = #"Someday";
}
else {
cell.detailTextLabel.text = fechaToDo;
}
}
//COLLAPSABLE/EXPANDABLE
else
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
// first row
cell.textLabel.text = #"Expandable"; // only top row showing
if ([expandedSections containsIndex:indexPath.section])
{
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
}
else
{
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown];
}
}
else
//FETCHED RESULTS
{
cell.accessoryView = nil;
ToDoItem *todoitem = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = todoitem.todoName;
NSDate *fechaToDO = todoitem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
NSString *valorSomeDay = todoitem.isSomeDay;
if ([valorSomeDay isEqualToString:#"issomeday"]){
cell.detailTextLabel.text = #"Someday";
}
else {
cell.detailTextLabel.text = fechaToDo;
}
}
}
}
return cell;
}
Any help is welcome to be able to show the first core data object and not the invented top row when expanding the sections.
It is also request to propose me another solution that could avoid the use of this invented top row when sections are collapsed..
Thank you.
You need to keep a mapping of your original index paths and the new index paths after you inserted the rows that resulted from the expansion.
If you implement it properly, you should be able to get the new index path from the old index path. Ex: item 3 is now 5 after row 1 was expanded and added 2 subrows.
EDIT: how to implement the mapping
You don't need to be experienced in iOS to implement it. I am not very experienced and I implemented it.
Create an array whose keys will be the index paths as the table view sees them (ie. 0 to 9 if you have 10 total rows), and the values are the index paths (or anything you want, really), that tell you what row in your datasource you are referencing (ie. 0, 1, 2, 3, 3.0, 3.1, 3.2, 4, 5, 6 if row 3 has 3 subrows currently expanded).
Whenever you expand (add) rows, insert them in that dictionary at the right place: in this example, when you expanded row 3, insert all 3 rows at index 4, 5, 6.
Whenever you collapse (remove) rows, delete them from that array.
Example:
0 => 0
1 => 1
2 => 2
3 => 3
4 => 4
5 => 5
6 => 6
becomes
0 => 0
1 => 1
2 => 2
3 => 3
4 => 3.0
5 => 3.1
6 => 3.2
7 => 4
8 => 5
9 => 6
when you expand row 3
I have two UITableViewCell's that each correspond to a Twitter Tweet or a Instagram Pic. As of now I have set it so that It will alternate between the two cells and have It go from an Twitter Tweet to an Instagram Pic. However I want to organize the UITableView so that it organizes both the Twitter Tweets and Instagram Pics chronologically in the TableView. Both the date keys for the Instagram API and the Twitter API are different. The Twitter API has a time key of created_at and Instagram's key is created_time. How would I organize both these Arrays? P.S. Both the arrays which the Tweets and Pics are in are NSMutableArray's.
Here is the Code that I have tried thus far:
// Setup for Cells
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *twitterCell = [self createTwitterCell:indexPath];
UITableViewCell *instagramCell = [self createInstagramCell:indexPath];
if (indexPath.row % 2 == 0) {
return twitterCell;
}else{
return instagramCell;
}
}
// Array Updater
- (void)updateArrays {
instaPics = self.timelineResponse[#"data"];
totalFeed = [tweets arrayByAddingObjectsFromArray:instaPics];
[self sortArrayBasedOndate:totalFeed];
}
// Current flawed method to organize by date
- (void)sortArrayBasedOndate {
NSDateFormatter *fmtDate = [[NSDateFormatter alloc] init];
[fmtDate setDateFormat:#"yyyy-MM-dd"];
NSDateFormatter *fmtTime = [[NSDateFormatter alloc] init];
[fmtTime setDateFormat:#"HH:mm"];
NSComparator compareDates = ^(id string1, id string2)
{
// Instagram Date Retrieval
NSDictionary *instagram = self.instaPics;
NSString *createdAt = instagram[#"created_time"];
int createdAtN = [createdAt intValue];
NSTimeInterval timestamp = (NSTimeInterval)createdAtN;
NSDate *date1 = [NSDate dateWithTimeIntervalSince1970:timestamp];
// Twitter Date Retrieval
NSDictionary *twitter = self.tweets;
NSDate *date2 = twitter[#"created_at"];
return [date1 compare:date2];
};
NSSortDescriptor * sortDesc1 = [[NSSortDescriptor alloc] initWithKey:#"start_date" ascending:YES comparator:compareDates];
[totalFeed sortUsingDescriptors:#[sortDesc1]];
}
If you guys need any more code excerpts feel free to ask :)
It seems like you're on the right track. Why don't you also format Twitter's time to match your formatting for Instagram's time?
NSComparator compareDates = ^(id string1, id string2)
{
// Instagram Date Retrieval
NSDictionary *instagram = self.instaPics;
NSString *createdAt = instagram[#"created_time"];
int createdAtN = [createdAt intValue];
NSTimeInterval timestamp = (NSTimeInterval)createdAtN;
NSDate *date1 = [NSDate dateWithTimeIntervalSince1970:timestamp];
// Twitter Date Retrieval
NSDictionary *twitter = self.tweets;
NSString *twitterCreated = twitter[#"created_at"];
int createdAtTwitter = [twitterCreated intValue];
NSTimeInterval timestampTwitter = (NSTimeInterval)createdAtTwitter;
NSDate *date2 = [NSDate dateWithTimeIntervalSince1970:timestampTwitter];
return [date1 compare:date2];
};