Files
UnrealEngine/Engine/Plugins/Online/IOS/OnlineSubsystemIOS/Source/Private/RetainedObjCInstance.h
2025-05-18 13:04:45 +08:00

151 lines
3.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include <type_traits>
/**
* RAII wrapper type that encapsulates manual memory management for Objective-C instances:
* - It calls retain when a non nil instance is received
* - It calls release on destruction
* - It handles copy/move semantics to keep reference counting consistent
* This type is useful because ARC is disabled for several reasons
*/
template <typename T>
class TRetainedObjCInstance
{
static_assert(std::is_pointer_v<T>, "T must be an Objective-C pointer type");
public:
/**
* Default constructor, initializes to nil.
*/
TRetainedObjCInstance()
:Ptr(nil)
{
}
/**
* Constructor, initializes instance and increases reference count if not nil.
*/
TRetainedObjCInstance(T InPtr)
:Ptr(InPtr?[InPtr retain]:nil)
{
}
/**
* Copy constructor, initializes instance and increases reference count if not nil.
*
* @param Other The Other object to copy from.
*/
TRetainedObjCInstance(const TRetainedObjCInstance& Other)
:TRetainedObjCInstance(Other.Ptr)
{
}
/**
* Move constructor, initializes instance. Sets other to nil without updating reference counting.
*
* @param Other The Other object to move from.
*/
TRetainedObjCInstance(TRetainedObjCInstance&& Other)
:Ptr(Other.Ptr)
{
Other.Ptr = nil;
}
/**
* Copy assignment, releases owned instance and retains received one.
*
* @param Other The Other object to copy from.
*/
TRetainedObjCInstance& operator=(const TRetainedObjCInstance& Other)
{
if(this != &Other)
{
[Ptr release];
Ptr = [Other.Ptr retain];
}
return *this;
}
/**
* Move assignment, releases owned instance, updates owned instance and clears Other.
*
* @param Other The Other object to move from.
*/
TRetainedObjCInstance operator=(TRetainedObjCInstance&& Other)
{
if(this != &Other)
{
[Ptr release];
Ptr = Other.Ptr;
Other.Ptr = nil;
}
return *this;
}
/**
* Destructor, releases owned instance if needed
*/
~TRetainedObjCInstance()
{
Reset();
}
/**
* Conversion operator to underlying instance. Useful to invoke Objective-C methods transparently
*/
operator T() { return Ptr; }
/**
* Conversion operator to underlying instance. Useful to invoke Objective-C methods transparently
*/
operator T() const { return Ptr; }
/**
* Releases ownership on Objective-C instance
*/
void Reset()
{
if(Ptr)
{
[Ptr release];
Ptr = nil;
}
}
friend bool operator==(const TRetainedObjCInstance<T>& Lhs, const TRetainedObjCInstance<T>& Rhs)
{
return Lhs.Ptr == Rhs.Ptr;
}
friend bool operator==(const TRetainedObjCInstance<T>& Lhs, T Rhs)
{
return Lhs.Ptr == Rhs;
}
friend bool operator==(T Lhs,const TRetainedObjCInstance<T>& Rhs)
{
return (Rhs == Lhs);
}
friend bool operator!=(const TRetainedObjCInstance<T>& Lhs, const TRetainedObjCInstance<T>& Rhs)
{
return Lhs.Ptr != Rhs.Ptr;
}
friend bool operator!=(const TRetainedObjCInstance<T>& Lhs, T Rhs)
{
return Lhs.Ptr != Rhs;
}
friend bool operator!=(T Lhs, const TRetainedObjCInstance<T>& Rhs)
{
return (Rhs != Lhs);
}
private:
/* Owned Objective-C instance */
T Ptr;
};