Incompatible block pointer types sending 'int (^)(__strong id, __strong id)' to parameter of type 'NSComparator'

时间秒杀一切 提交于 2019-12-13 14:40:54

问题


Getting below error in GPUImage Library when moved from xcode 5.0 to 5.1. After searching on google i found that i need to send int like this [NSNumber numberWithInt:number] but issue is that i dont have control on the value getting passed to sortedArrayUsingComparator in below given code.

Error Log:

Incompatible block pointer types sending 'int (^)(__strong id, _strong id)' to parameter of type 'NSComparator' (aka 'NSComparisonResult (^)(_strong id, __strong id)')

Error on this line : NSArray *sortedPoints = [points sortedArrayUsingComparator:^(id a, id b) {

- (id) initWithCurveFile:(NSString*)curveFile
{    
    self = [super init];
    if (self != nil)
    {
        NSString *bundleCurvePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: curveFile];

        NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath: bundleCurvePath];

        if (file == nil)
        {
            NSLog(@"Failed to open file");

            return self;
        }

        NSData *databuffer;

        // 2 bytes, Version ( = 1 or = 4)
        databuffer = [file readDataOfLength: 2];
        version = CFSwapInt16BigToHost(*(int*)([databuffer bytes]));

        // 2 bytes, Count of curves in the file.
        [file seekToFileOffset:2];
        databuffer = [file readDataOfLength:2];
        totalCurves = CFSwapInt16BigToHost(*(int*)([databuffer bytes]));

        NSMutableArray *curves = [NSMutableArray new];

        float pointRate = (1.0 / 255);
        // The following is the data for each curve specified by count above
        for (NSInteger x = 0; x<totalCurves; x++)
        {
            // 2 bytes, Count of points in the curve (short integer from 2...19)
            databuffer = [file readDataOfLength:2];            
            short pointCount = CFSwapInt16BigToHost(*(int*)([databuffer bytes]));

            NSMutableArray *points = [NSMutableArray new];
            // point count * 4
            // Curve points. Each curve point is a pair of short integers where 
            // the first number is the output value (vertical coordinate on the 
            // Curves dialog graph) and the second is the input value. All coordinates have range 0 to 255. 
            for (NSInteger y = 0; y<pointCount; y++)
            {
                databuffer = [file readDataOfLength:2];
                short y = CFSwapInt16BigToHost(*(int*)([databuffer bytes]));
                databuffer = [file readDataOfLength:2];
                short x = CFSwapInt16BigToHost(*(int*)([databuffer bytes]));

                [points addObject:[NSValue valueWithCGSize:CGSizeMake(x * pointRate, y * pointRate)]];
            }

            [curves addObject:points];
        }

        [file closeFile];

        rgbCompositeCurvePoints = [curves objectAtIndex:0];
        redCurvePoints = [curves objectAtIndex:1];
        greenCurvePoints = [curves objectAtIndex:2];
        blueCurvePoints = [curves objectAtIndex:3];
    }

    return self;

}


- (NSArray *)getPreparedSplineCurve:(NSArray *)points

{

    if (points && [points count] > 0) 

    {

        // Sort the array.

        NSArray *sortedPoints = [points sortedArrayUsingComparator:^(id a, id b) {

            float x1 = [(NSValue *)a CGPointValue].x;

            float x2 = [(NSValue *)b CGPointValue].x;  

            return x1 > x2;

        }];

        // Convert from (0, 1) to (0, 255).

        NSMutableArray *convertedPoints = [NSMutableArray arrayWithCapacity:[sortedPoints count]];

        for (int i=0; i<[points count]; i++){

            CGPoint point = [[sortedPoints objectAtIndex:i] CGPointValue];

            point.x = point.x * 255;

            point.y = point.y * 255;

            [convertedPoints addObject:[NSValue valueWithCGPoint:point]];

        }


        NSMutableArray *splinePoints = [self splineCurve:convertedPoints];

        // If we have a first point like (0.3, 0) we'll be missing some points at the beginning

        // that should be 0.

        CGPoint firstSplinePoint = [[splinePoints objectAtIndex:0] CGPointValue];

        if (firstSplinePoint.x > 0) {

            for (int i=0; i <=firstSplinePoint.x; i++) {

                CGPoint newCGPoint = CGPointMake(0, 0);

                [splinePoints insertObject:[NSValue valueWithCGPoint:newCGPoint] atIndex:0];

            }

        }


        // Prepare the spline points.

        NSMutableArray *preparedSplinePoints = [NSMutableArray arrayWithCapacity:[splinePoints count]];

        for (int i=0; i<[splinePoints count]; i++) 

        {

            CGPoint newPoint = [[splinePoints objectAtIndex:i] CGPointValue];

            CGPoint origPoint = CGPointMake(newPoint.x, newPoint.x);

            float distance = sqrt(pow((origPoint.x - newPoint.x), 2.0) + pow((origPoint.y - newPoint.y), 2.0));

            if (origPoint.y > newPoint.y) 

            {

                distance = -distance;

            }

            [preparedSplinePoints addObject:[NSNumber numberWithFloat:distance]];

        }

        return preparedSplinePoints;

    }

    return nil;
}

回答1:


A comparison block must return a NSComparisonResult, which is NSOrderedAscending, NSOrderedSame, or NSOrderedDescending (a.k.a. -1, 0, +1), depending on whether the first element is smaller, equal to or larger than the second element).

Returning x1 > x2 does not fulfill this requirement, and the compiler complains because it "infers" the return type as int from the last statement.

To solve this problem, you can

  • use the technique from Is there a standard sign function (signum, sgn) in C/C++? to return -1, 0, or +1, and
  • declare the return type of the block explicitly as NSComparisonResult  to make the compiler happy.

You can also simplify the code slightly by declaring the block parameters as NSValue *.

NSArray *sortedPoints = [points sortedArrayUsingComparator:^NSComparisonResult(NSValue *a, NSValue *b) {
    float x1 = [a CGPointValue].x;
    float x2 = [b CGPointValue].x;
    return (x1 > x2) - (x2 > x1); // -1, 0, or +1
}];



回答2:


Your calls to CFSwapInt16BigToHost are wrong. Did it occur to you that passing a 32 bit int to a function swapping bytes in a 16 bit into cannot be right? And that reading 4 bytes from an NSData object containing only two bytes cannot be right?

You got an error message. It seems very clear to me. It tells you which parameter was expected, and which you gave it. When you get an error message, don't get your brain into a mush and think "oh my god, the code fairies are against me and I need some magic that I don't know". You need to think: "There is an error in my code. Which error is it? " In this case, it is obvious. The error message tells you. You need a block returning an NSComparisonResult.

The next step should have been to look for the definition of NSComparisonResult. There you would find that you are expected to return one of three possible values, while your function only returns one of two possible values. So if you just made it compile, it wouldn't sort properly.

You could have used code completion, which would have filled out a skeleton for the block with all the right types, so you wouldn't have had a chance to get this wrong in the first place. You should also find Apple's documentation of blocks, and find out how the return type is determined. Reading documentation is a very good way to learn and become a better programmer.




回答3:


I got the same error. The solution is as suggested by others and I am trying to put it in a simple way:
Change the block from:
^(id a, id b)
to:
^NSComparisonResult(id a, id b)
Then you are all set.



来源:https://stackoverflow.com/questions/22398455/incompatible-block-pointer-types-sending-int-strong-id-strong-id-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!