Possible Bug arrowsforOrientation:atGridCoord on rotate


#1

Hi Guys,

I am getting a crash in in my app when I am rotating, and then recreating the shinobi grid. I am seeing the following error

0x1053c780a: movq 0x15dc4f(%rip), %rsi ; "respondsToSelector:"
0x1053c7811: movq 0x15ad48(%rip), %rdx ; "shinobiGrid:arrowImageForOrientation:forCellAtCoord:"
0x1053c7818: movq %rax, %rdi
0x1053c781b: callq *%r15
0x1053c781e: testb %al, %al
0x1053c7820: je 0x1053c7870 ; -[ShinobiGrid arrowForOrientation:atGridCoord:] + 238

It is looking like the ShinobiGrid arrowsforOrientation:atGridCoord is throwing the error.

Any ideas?

Thanks,

John


#2

Greetings Program!

First time I’ve seen that on a rotation; I can try to recreate the problem.

What do you mean by “recreating” the grid? How are you handling the rotation? Are you redefining the grid and adding it again or just changing the grid frame bounds?

How do you have your grid set up? What type of grid cells do you have in your grid?

Wg


#3

Hi there,

Well, on orientation change I remove the grid from the superView and “recreate it” but doing the following…

// create a grid - with a 40 pixel padding
    // based on the orientation we have to set the frame differently?
    _shinobiDataGrid = [[ShinobiDataGrid alloc] initWithFrame:/*CGRectInset(self.view.frame,0,40)*/self.view.bounds];
    _shinobiDataGrid.dataSource = self;
    [_shinobiDataGrid setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
    


    
    
    /**
     * Set the default values for the grid
     *
     * - selected rows
     * - basic row
     * - alternate row
     * - header
     */
    
    UIColor *superLightGray = [UIColor colorWithRed:252.0/255.0 green:252.0/255.0 blue:252.0/255.0 alpha:1.0];
    UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
    
    SDataGridCellStyle *rowStyle = [[SDataGridCellStyle alloc] init];
    rowStyle.font = [UIFont fontWithName:@"Avenir" size:fontSizeCell];
    rowStyle.backgroundColor = [UIColor whiteColor];
    rowStyle.textColor = [UIColor darkGrayColor];
    rowStyle.contentInset = padding;
    
    SDataGridCellStyle *rowAlternatingStyle = [[SDataGridCellStyle alloc] init];
    rowAlternatingStyle.font = [UIFont fontWithName:@"Avenir" size:fontSizeCell];
    //rowAlternatingStyle.backgroundColor = superLightGray;
    
    SDataGridCellStyle *headerStyle = [[SDataGridCellStyle alloc] init];
    headerStyle.font = [UIFont fontWithName:@"Avenir-Heavy" size:fontSizeHeader];
    headerStyle.backgroundColor = superLightGray;//[UIColor whiteColor];
    headerStyle.textColor = [UIColor colorWithRed:30.0/255.0 green:30.0/255.0 blue:30.0/255.0 alpha:1.0];
    
    
    SDataGridCellStyle* selectedRowStyle = [[SDataGridCellStyle alloc] init];
    selectedRowStyle.font = [UIFont fontWithName:@"Avenir" size:fontSizeCell];
    selectedRowStyle.backgroundColor = [UIColor colorWithRed:85.0/255.0 green:85.0/255.0 blue:85.0/255.0 alpha:0.75];
    selectedRowStyle.textColor = superLightGray;
    
    // once we have created our SDataGridCellStyle objects
    // we can set them to the properties in the grid.
    _shinobiDataGrid.defaultCellStyleForRows = rowStyle;
    _shinobiDataGrid.defaultCellStyleForAlternateRows = rowAlternatingStyle;
    _shinobiDataGrid.defaultCellStyleForHeaderRow = headerStyle;
    _shinobiDataGrid.defaultCellStyleForSelectedRows = selectedRowStyle;
    
    /**
     * Vertical line support
     *
     * Vertical lines were removed in the ios7 version of Shinobi
     * because it does not align with the style. BUT, if we wish
     * to turn it on, here is the code.
     */
    
    SDataGridTheme *verticalLinesTheme = [SDataGridiOS7Theme new];
    
    // dont show the vertical lines in the grid
    verticalLinesTheme.hideVerticalGridlines = NO;
    
    // row styles
    verticalLinesTheme.alternateRowStyle = rowAlternatingStyle;
    verticalLinesTheme.rowStyle = rowStyle;
    verticalLinesTheme.selectedCellStyle = selectedRowStyle;
    verticalLinesTheme.headerRowStyle = headerStyle;
    
    [verticalLinesTheme setGridLineStyle:[SDataGridLineStyle styleWithWidth:0.3f
                                                                  withColor:veryLightGray]];

    
    [_shinobiDataGrid applyTheme:verticalLinesTheme];
    
    
    /**
     * Remove the border on the grid
     */
    _shinobiDataGrid.layer.borderWidth = 0;
    
    /**
     * Define the columns for the grid by passing the data and the grid
     * to the method.
     */
    [self generateGridColumnsWithGridData:_data forGrid:_shinobiDataGrid];
    
    /**
     * Final check on the data to see if we actually have a column.
     */
    if( _data.count > 0 ){
        [self.view addSubview:_shinobiDataGrid];
    }

And the generate columns method is here

-(void)generateGridColumnsWithGridData:(NSArray *)gridData forGrid:(ShinobiDataGrid *)grid{
    
    if( !gridData )
        return;
    
    /**
     * @var NSDictionary rowData the dictionary holding the key/value pairs for the row
     */
    NSDictionary *rowData = [gridData objectAtIndex:0];
    
    /**
     * @var NSArray cols the column "keys" from the rowData dictionary
     */
    NSArray *cols = [rowData allKeys];
    
    /**
     * @var NSUInteger numCols the number of columns total in the grid
     */
    NSUInteger numCols = cols.count;
    
    /**
     * loop through all of the grid data in the FIRST row
     * and generate a column for each element in the row data
     */
    for (NSString *columnHeading in cols ) {
        // intantiate the SDataGridColumn
        double width = self.view.bounds.size.width/numCols;
        SDataGridColumn* column = [[SDataGridColumn alloc] initWithTitle:columnHeading];
        column.width = [NSNumber numberWithDouble:250.0];
        [grid addColumn:column];
    }
}

So when I rotate once in the simulator sometimes it works, and then the second time I try to rotate back chances are it will crash.

The orientation is handled as follows:

-(void)orientationChanged:(NSNotification *)notification{
    NSLog(@"got orientation notification");
    [_shinobiDataGrid removeFromSuperview];
    [self generateGrid];
}

#4

What version of the framework are you using? I didn’t experience the issue using your code.

Using the GettingStarted sample app, I put your first block of code as is into the generateGrid method adding variables for fontSizeCell and fontSizeHeader. I added an array of dictionary for generating the columns:

float fontSizeCell = 12;
float fontSizeHeader = 14;
NSArray *_data = @[@{ @"Name" : @"Name", @"Age" : @"Age" }];

In the generateGridColumnsWithGridData method you could probably just send the first row instead of all the data.

I moved the width calculation outside of the loop and changed the static 250 to the variable.

NSNumber *width = [NSNumber numberWithDouble:self.view.bounds.size.width/numCols];

for (NSString *columnHeading in cols ) {
    // intantiate the SDataGridColumn
    SDataGridColumn* column = [[SDataGridColumn alloc] initWithTitle:columnHeading];
    column.width = width;
    [grid addColumn:column];
}

Instead of orientationChanged notification, I used the following:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    
    NSLog(@"got orientation notification");
    [_shinobiDataGrid removeFromSuperview];
    [self generateGrid];
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

Wg


#5

An after thought; try using this to refresh the grid to the new size instead of removing and recreating it in didRotateFromInterfaceOrientation:

_shinobiDataGrid.frame = /*CGRectInset(self.view.frame,0,40)*/self.view.bounds;//CGRectInset(self.view.bounds, 40,40);
NSNumber *width = [NSNumber numberWithDouble:_shinobiDataGrid.frame.size.width/_shinobiDataGrid.columns.count];

for (SDataGridColumn *column in _shinobiDataGrid.columns)
{
    column.width = width;
}

[_shinobiDataGrid reload];

Wg