Using CF_SWIFT_NAME to import a C struct getter and setter that bridges to Foundation from Core Foundation

84 views Asked by At

I have a struct, House, that I want usable in both Objective-C and in Swift (additionally, I just wanted to test the bounds of what I could and couldn't import from C to Swift).

House is defined as follows:

typedef struct {
    NSUInteger number;
    CFStringRef street CF_REFINED_FOR_SWIFT;
    CFStringref city CF_REFINED_FOR_SWIFT;
    StateCode stateCode; // an enum, whose definition isn't relevant to this question 
    NSUInteger zip;
} House;

To avoid using Unmanaged<T> in Swift, street and city each have accessor methods that bridge the underlying CFStringRef to NSString*. The accessors for city are practically identical, so I'll omit them here and only provide the accessors for street.

House.h

NSString* HouseGetStreet(const House* h) CF_SWIFT_NAME(getter:House.street(self:));
void HouseSetStreet(House* h, NSString* newStreet) CF_SWIFT_NAME(setter:House.street(self:newStreet:));

House.m

NSString* HouseGetStreet(const House* h) {
    return [(__bridge NSString*)h->street copy];
}

void HouseSetStreet(House* h, NSString* newStreet) {
    CFStringRef* currentStreet = &h->street;
    CFStringRef street2 = (__bridge CFStringRef)street; // don't retain yet

        if (*currentStreet != street2) {
            CFRelease(*currentStreet);
            *currentStreet = CFRetain(street2); // now we retain
        } else {
            return;
    }
}

When defining only the getter method, Swift imports the street property as a Swift.String and everything works fine. But when I define the setter methods, Swift acts like the street property doesn't even exist and I can't get or set the field from Swift code.

0

There are 0 answers