Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save knebekaizer/8e924ba8732f914d10c3ccb533831ebb to your computer and use it in GitHub Desktop.
Save knebekaizer/8e924ba8732f914d10c3ccb533831ebb to your computer and use it in GitHub Desktop.
template <bool retainAutorelease>
static ALWAYS_INLINE id Kotlin_ObjCExport_refToObjCImpl(ObjHeader* obj) {
if (obj == nullptr) return nullptr;
if (obj->has_meta_object()) {
id associatedObject = GetAssociatedObject(obj);
if (associatedObject != nullptr) {
return retainAutorelease ? objc_retainAutoreleaseReturnValue(associatedObject) : associatedObject;
}
}
// TODO: propagate [retainAutorelease] to the code below.
convertReferenceToObjC converter = (convertReferenceToObjC)obj->type_info()->writableInfo_->objCExport.convert;
if (converter != nullptr) {
return converter(obj);
}
return Kotlin_ObjCExport_refToObjC_slowpath(obj);
}
/**
Здесь нехорошо то, что функция `Kotlin_ObjCExport_refToObjCImpl` смешивает две проблемных области (domains):
1. Business domain: create and store (slow path) or fetch (fast path) the associated object
2. ARC domain: retain policy
Try orthogonal design by Separation of Concerns: separate policy from business code:
*/
template <typename RetainAutoreleasePolicy>
static ALWAYS_INLINE id Kotlin_ObjCExport_refToObjCImpl(ObjHeader* obj) {
if (obj == nullptr) return nullptr;
if (obj->has_meta_object()) {
if (id associatedObject = GetAssociatedObject(obj)) {
return RetainAutoreleasePolicy(associatedObject);
}
}
// ... no changes below...
}
/// Usage example:
std::function<id (id)> doRetain = [](id obj) { return objc_retainAutoreleaseReturnValue(obj); };
std::function<id (id)> doNotRetain = [](id obj) { return obj; };
id foo = Kotlin_ObjCExport_refToObjCImpl<doRetain>(obj);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment