custom UItableView not displaying correctly on ios8 - ios

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

Related

YapDatabase sorting confounds editing update

In a UITableViewController I use YapDatabase with Mantle sorting the following way:
YapDatabaseViewSorting *viewSorting = [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(NSString *group, NSString *collection1, NSString *key1, XQBuilding *object1, NSString *collection2, NSString *key2, XQBuilding *object2) {
if ([group isEqualToString:XQBuildingsViewGroupName]) {
return [[object1 name] compare:[object2 name] options:NSNumericSearch];
}
if ([group isEqualToString:XQPicturesGroup]) {
return [[object1 updatedAt] compare:[object2 updatedAt]];
}
return NSOrderedSame;
}];
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
options.isPersistent = NO;
YapDatabaseView *databaseView = [[YapDatabaseView alloc] initWithGrouping:viewGrouping sorting:viewSorting versionTag:#"" options:options];
Although the used option I have sometimes (when an edited name changes the edited item order in the list) incorrect indexPath on reading:
- (UITableViewCell*)editableTableView:(UITableView *)tableView simpleCellForIndexPath:(NSIndexPath *)indexPath
{
__block XQBuilding *building;
__block NSNumber *gla;
[self.readConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
building = [[transaction ext:XQBuildingListYapName] objectAtIndexPath:indexPath withMappings:self.tableViewAnimator.viewMappings];
gla = [building glaWithTransaction:transaction];
}];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"BuildingCell"];
cell.textLabel.text = building.name;
cell.detailTextLabel.text = [NSString stringWithFormat: #"%# sqm", formatDecimal(gla)];
return cell;
}
i. e. building in such case is a different one than was edited. How to get a correct indexPath according to actual sorting?
There are plenty of things that should be correctly coded to make it work properly!
As I can see from your code you use YapDatabaseViewMappings. Do you use LongLivedReadTransactions and do you subscribe to YapDatabaseModifiedNotification to properly modify the table on database changes?
There is an simplified example that shows how to use all these things to update your UITableView in real time right after database is updated.

How can we display number values in UILabels in iOS?

I am very new for iOS and in my app I am integrating services and after getting response from service I am storing the values in Array-list.
When I load that array list values in tableList showing exception like:
_Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x7d7ca000'
McoIdArray:-(
106314100491,
106314100492,
106314100493,
106314100494,
106314100495
)
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"MyCell";
Cell = (CoridersCell *)[tableList dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (Cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CoridersCell" owner:self options:nil];
Cell = [nib objectAtIndex:0];
}
Cell.mcoId.text = [McoIdArray objectAtIndex:indexPath.row];
return Cell;
}
The problem is you are assigning an NSNumber instance instead of an NSString. You should format the number to a string like this:
NSNumber* number = [McoIdArray objectAtIndex:indexPath.row];
cell.mcoId.text = [NSString localizedStringWithFormat:#"%#", number];
If you want to have more control over number formatting you can use NSNumberFormatter.
Your array contains instances of NSNumber, not NSString. So you can't directly assign the value from the array to the label's text property. You must first convert the NSNumber to an NSString.
One option is to use the stringValue method.
Cell.mcoId.text = [McoIdArray[indexPath.row] stringValue];
Also note the use of modern syntax to access the array.
Replace the line:
Cell.mcoId.text = [McoIdArray objectAtIndex:indexPath.row];
with the line I show above.

"Format string is not string literal (potentially insecure)" [duplicate]

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]];

Multiple methods named 'location' found with mismatched result, parameter type, or attributes

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".

TableView cells are being slow when scrolling

I have a tableView which shows a list of Facebook friends. I have an imageview within the cell which displays the profilePicture of the user. Using AFNetworking I call the new image and put a placeholder whilst loading.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"FbFriendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSDictionary *friend = (NSDictionary *)[self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = [friend valueForKey:#"name"];
} else {
NSDictionary *friend = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
UIImageView *profilePic = (UIImageView *)[cell.contentView viewWithTag:10];
UILabel *displayName = (UILabel *)[cell.contentView viewWithTag:20];
UIButton *playButton = (UIButton *)[cell.contentView viewWithTag:30];
displayName.text = [friend valueForKey:#"name"];
UIImage *defaultPhoto = [UIImage imageNamed:#"person.png"];
NSString *urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%#/picture", friend[#"id"]];
NSURL *avatarUrl = [NSURL URLWithString:urlString];
[profilePic setImageWithURL:avatarUrl placeholderImage:defaultPhoto];
profilePic.contentMode = UIViewContentModeScaleAspectFit;
}
This is causing some speed/performance issues for the tableview. Does anyone know why this would be, is this setup correctly?
The cells are prototype cells created with a storyboard. I also have other code for the other objects in the cell, but removing the profile Picture section makes the cell perform normally so this appears to be the issue, just not sure why.
EDIT
UIImage *defaultPhoto = [UIImage imageNamed:#"person40x40.png"];
NSString *urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?width=40&height=40", friend[#"id"]];
I have updated the pictures to fit the 40x40 image view but no difference. The iphone4 is slow to load the table cells. Compared to an iphone5 which is extremely smooth in scrolling.
Here is the heaviest in Time Profiler:
Looks like profilePic is the worst. This is because of the Data request from Facebook. I have changed the profilePic to only be the default Pic which is not a URL request and the table view is fine. So this is clearly an issue with performance for the setImageWithURL.
Looking at other questions it appears to be the best way to accomplish this though :- Best practices for managing facebook friends pics in iOS App
Any thoughts welcome
Auto-layout can cause some issues. Also, if you are resizing the images as they come in, that can cause slowness. The easiest way to tell for sure is to run Time Profiler (with Hide System Libraries and Show Obj-C Only checked). This will tell you where your slowness is coming from.
I now have few idea to improve your performance problem.
1) Requesting your friend improvment
From your edit it look like requestion your friend also take a fair amount of time:
NSDictionary *friend = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
I'm sure you can cache most of this call with something like:
-(void)viewDidLoad{
[super viewDidLoad];
this.friendsInsensitive = [self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
2) Web request improvement 1/2
reading few post about NSURLConnection and the event loop and blocking the main thread with async call
Let try something. Call the image web request in an other thread.
[...]
UIImageView *profilePic = (UIImageView *)[cell.contentView viewWithTag:10];
UILabel *displayName = (UILabel *)[cell.contentView viewWithTag:20];
UIButton *playButton = (UIButton *)[cell.contentView viewWithTag:30];
displayName.text = [friend valueForKey:#"name"];
UpdateImgContainter *containter = [UpdateImgContainter alloc] initWithCell:cell andFriendId:friend[#"id"];
[self performSelectorInBackground:#selector(requestImg:) withObject:containter];
}
-(void)requestImg:(UpdateImgContainter *)containter{
UIImage *defaultPhoto = [UIImage imageNamed:#"person.png"];
NSString *urlString = [NSString stringWithFormat:#"https://graph.facebook.com/%#/picture", containter.friendId];
NSURL *avatarUrl = [NSURL URLWithString:urlString];
[profilePic setImageWithURL:avatarUrl placeholderImage:defaultPhoto]; //warning it's not good practice to upload the UI from an other thread than MainThread
profilePic.contentMode = UIViewContentModeScaleAspectFit;
}
2) Web request improvement 2/2
I just find out an other way to do it. And it's probably more reliable.
Download this LazyTableImages project from Apple itself. It was create exactly to teach the probleme you are facing.
At the end of the day I just think setImageWithURL: is maybe not that quick (?) and the point N°1 was probably part of your problem too. Looking a LazyTableImages project Apple simply use a NSURLConnection.

Resources