2

I am trying to get an old project to work with ARC in iOS 10.2 (the project began under iOS 4). In two places I get the following warning

    Passing 'CFTypeRef _Nullable' (aka 'const void *') to parameter of type 'void * _Nullable' discards qualifiers

The first happens in setUpPlayQueue at line CFBridgingRetain(self),.

- (void)setUpPlayQueue
{
    AudioQueueNewOutput(
        &audioFormat,
        playCallback,
        CFBridgingRetain(self), 
        NULL,                   // run loop
        kCFRunLoopCommonModes,  // run loop mode
        0,                      // flags
        &playQueue
        );

    self.gain = 1.0;
}

setUpPlayQueue is called from setUpAudio

- (void)setUpAudio
{
    if (playQueue == NULL)
    {
        [self setUpAudioSession];
        [self setUpPlayQueue];
        [self setUpPlayQueueBuffers];
    }
}

The second happens in primePlayQueueBuffers at line playCallback(CFBridgingRetain(self), playQueue, playQueueBuffers[t]);

- (void)primePlayQueueBuffers
{
    for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t)
    {
        playCallback(CFBridgingRetain(self), playQueue, playQueueBuffers[t]);
    }
}

primePlayQueueBuffers is called from start

- (void)start
{
    if (!playing)
    {
        playing = YES;
        [self primePlayQueueBuffers];
        AudioQueueStart(playQueue, NULL);
    }
}

By setting the -fno-objc-arc compiler flag for the build target (as described here), I managed to disable ARC for AudioBufferPlayer(the file holding these methods) and get the project to build. Similar problems described here here and here offered no way to actually fix this problem.

Can anyone help please ? Thanks

Update

At the suggestion of Martin (and Amin), when I use (__bridge void *)(self) instead of CFBridgingRetain(self) - with the -fno-objc-arc compiler flag cleared - both warnings disappear. However when I build Xcode then reports

    Existing instance variable 'delegate' for property 'delegate' with assign attribute must be __unsafe_unretained

Here is the delegate interface

@interface AudioBufferPlayer : NSObject <AVAudioSessionDelegate>

{
    id<AudioBufferPlayerDelegate> delegate;
    BOOL playing;
    Float32 gain;
    AudioStreamBasicDescription audioFormat;

    /// the audio queue object being used for playback
    AudioQueueRef playQueue;

    /// the audio queue buffers for the playback audio queue
    AudioQueueBufferRef playQueueBuffers[NUMBER_AUDIO_DATA_BUFFERS];

    /// the number of audio data packets to use in each audio queue buffer
    UInt32 packetsPerBuffer;

    /// the number of bytes to use in each audio queue buffer
    UInt32 bytesPerBuffer;
}

/*! 
 * The delegate that fills up the audio buffers. This is a weak reference; the 
 * delegate is not retained. 
 */
@property (nonatomic, assign) id<AudioBufferPlayerDelegate> delegate;

In Transitioning to ARC Release Notes it says

Weak references are not supported in … iOS 4.

When I changed the property reference to strong and tried to build, Xcode initially reported several errors including one caused by a dealloc which I am reasonably certain Xcode had reinstated in the code (I know I had previously removed it). However after closing Xcode and reopening it, I am now able to build and run the project successfully with no errors or warnings.

Thanks Martin and Amin. Much appreciated.

Community
  • 1
  • 1
Greg
  • 1,750
  • 2
  • 29
  • 56
  • Using `__bridge_retained()` didn't solve the problem? – Amin Negm-Awad Mar 18 '17 at 05:43
  • 1
    IIRC it does not take away a qualifier. However, you pass an argument with pointer to const to a parameter without const. Since it is an object in your case, simply casting it should be harmless. – Amin Negm-Awad Mar 18 '17 at 06:05
  • Amin, I can silence both warnings using `(__bridge id`) e.g. `(__bridge id)CFBridgingRetain(self),` and `playCallback((__bridge id)CFBridgingRetain(self), playQueue, playQueueBuffers[t]);`. But as soon as I clear the `-fno-objc-arc` compiler flag, Xcode reports “Implicit conversion of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast” – Greg Mar 18 '17 at 07:20
  • 2
    `(__bridge_retained void *)(self)` or `(__bridge void *)(self)` – depending on whether you want to retain self or not – (as suggested by Amin) should work and compile without warnings. – Martin R Mar 18 '17 at 10:54
  • Martin and Amin, I believe you put me on the right track. See my update. – Greg Mar 18 '17 at 12:08

0 Answers0