NSObject PerformSelector问题

时间:2010-07-14 20:15:21

标签: c++ objective-c multithreading memory-management core-data

Hooooookay所以这是另一个“我只是不知道发生了什么”问题:

我第一次拨打下面getFullWL()的电话时,会按预期获得所有值。但是,每次后续调用都返回nan而不是真值(XCode中的-nan(0x400000000)或其他内容)

此外,如果我将“调试”行放在SFLog中,则值打印为nan ,但会返回正确的值!如果我注释掉SFLog (这只是NSLog的#define,具体取决于我设置的级别 - 没什么特别的),然后isnan()中的View没有抓住该值,但会将其检查为isnan() } Window

WindowView坐在一个帖子上,而DataModuleDCMPix坐在另一个帖子上(主线程,我相信)。 DCMPix也从Core-Data对象中获取一些数据(我相信fImage)。

void Window::PopUp()
{
    // Grab the View from the Pipe Thread and cast it to my local namespace subclass View
    View *view = static_cast< View* >(getPipe()->getView(event.context.view));

    float fullww = view->getFullWW();
    float fullwl = view->getFullWL();
    //SFLog(@"WindowLevel Window %f", wl);

    // set SLider Values
    if (!isnan(fullwl)){
        [[vc winLevel] setMinValue:fullwl];
        [[vc winLevel] setMaxValue:(-1.0f*fullwl)];
    }
}


float View::getFullWL()
{
    float wl = _callPixMethod(@selector(fullwl)).floatValue;
    if ( isnan(wl) ) wl = _wl * 2.0f; //<-- is never detected as NaN here
    //SFLog(@"WindowLevel View %f", wl);  //<-- but is *printed* as NaN here
    return wl;
}

// A Union to "cast" the return from the [object performSelector:] method.
//   Since it returns `id` and (float)(id) doesn't work.
union performReturn {
    id OBJC_ID;
    int intValue;
    float floatValue;
    bool boolValue;
};


performReturn View::_callPixMethod(SEL method)
{
    DataModule* data;
    DataVisitor getdata(&data);
    getConfig()->accept(getdata);
    performReturn retVal;
    retVal.OBJC_ID = data->callPixMethod(_datasetIndex, _datasetID, method);
    return retVal;
}


id DataModule::callPixMethod(int index, std::string predicate, SEL method)
{
    DCMPix *pix =[[getSeriesData(predicate) pixList_] objectAtIndex:index];

    pthread_mutex_lock(&_mutex);

    id retVal = [pix performSelector:method];

    pthread_mutex_unlock(&_mutex);

    return retVal;
}

// DCMPix.m (from API, can't change)
- (float) fullwl
{
 if( fullww == 0 && fullwl == 0) [self computePixMinPixMax];
 return fullwl;
}

- (void)computePixMinPixMax
{
    float pixmin, pixmax;

    if( fImage == nil || width * height <= 0) return;

    [checking lock];

    @try 
    {
        if( isRGB)
        {
            pixmax = 255;
            pixmin = 0;
        }
        else
        {
            float fmin, fmax;

            vDSP_minv ( fImage,  1, &fmin, width * height);
            vDSP_maxv ( fImage , 1, &fmax, width * height);

            pixmax = fmax;
            pixmin = fmin;

            if( pixmin == pixmax)
            {
                pixmax = pixmin + 20;
            }
        }

        fullwl = pixmin + (pixmax - pixmin)/2;
        fullww = (pixmax - pixmin);
    }
    @catch (NSException * e) 
    {
        NSLog( @"***** exception in %s: %@", __PRETTY_FUNCTION__, e);
    }

    [checking unlock];
}

帮助!为什么我在Window中没有得到正确的值?

调用nan时,我也没有view->getFullWW(),即使它遵循相同的执行路径。 (但调用@selector(fullww)

不会引发错误或异常。只是那种奇怪的行为。

谢谢!


经过进一步测试后,以下变化会产生重大影响:

float View::getFullWL()
{
    float wl = _callPixMethod(@selector(fullwl)).floatValue;
    if ( isnan(wl) ) wl = _wl * 2.0f; //<-- is never detected as NaN here
    NSLog(@"WindowLevel View %f", wl);  //<-- is *printed* as NaN here
    return wl; //<-- returns expected value
}

float View::getFullWL()
{
    float wl = _callPixMethod(@selector(fullwl)).floatValue;
    if ( isnan(wl) ) wl = _wl * 2.0f; //<-- is never detected as NaN here
    return wl; //<-- returns `nan`
}

经过更多测试后,如果在NS {({1}}被分配之前发生了NSLog()语句的位置并不重要。

float fullwl =

1 个答案:

答案 0 :(得分:1)

Whelp,我在这里回答我自己的问题再次,但答案是...... RTFM

  

aSelector参数应标识不带参数的方法。对于返回除对象以外的任何内容的方法,请使用NSInvocation

答案是,使用NSInvocation而非[obj performSelector:]