rust_macios/objective_c_runtime/
traits.rs

1use objc::{
2    msg_send,
3    runtime::{Class, Protocol, Sel},
4    sel, sel_impl,
5};
6
7use crate::{
8    foundation::{NSString, UInt},
9    utils::to_bool,
10};
11
12use super::id;
13
14/// The group of methods that are fundamental to all Objective-C objects.
15pub trait INSObject {
16    /* Creating, Copying, and Deallocating Objects
17     */
18
19    /// Implemented by subclasses to initialize a new object (the receiver) immediately after memory for it has been allocated.
20    fn new() -> Self;
21
22    /// Returns a an `id`.
23    fn to_id(self) -> id;
24
25    /// Returns `Self` representation of the object.
26    ///
27    /// # Safety
28    ///
29    /// This function dereferences a raw pointer
30    unsafe fn from_id(obj: id) -> Self;
31
32    /* Describing Objects
33     */
34
35    /// Returns a string that represents the contents of the receiving class.
36    fn description(&self) -> NSString;
37
38    /* Supporting Discardable Content
39     */
40
41    /// Returns a string that represents the contents of the receiving class.
42    fn debug_description(&self) -> NSString;
43
44    /* Obselte Methods
45     */
46
47    /// Increments the receiver’s reference count.
48    fn retain(&self) -> Self;
49}
50
51/// The group of methods that are fundamental to all Objective-C objects.
52pub trait PNSObject {
53    ///  Allocates a new instance of the receiving class, sends it an init message, and returns the initialized object.
54    fn m_new() -> Self
55    where
56        Self: Sized + FromId,
57    {
58        unsafe { Self::from_id(msg_send![Self::m_class(), new]) }
59    }
60
61    /// Returns a new instance of the receiving class.
62    fn m_alloc() -> Self
63    where
64        Self: Sized + FromId,
65    {
66        unsafe { Self::from_id(msg_send![Self::m_class(), alloc]) }
67    }
68
69    /// Initializes the class before it receives its first message.
70    fn m_initialize() {
71        unsafe { msg_send![Self::m_class(), initialize] }
72    }
73
74    /* Identifying Classes
75     */
76
77    /// Returns the class object for the receiver’s class.
78    fn m_class<'a>() -> &'a Class;
79
80    /// Returns the class object for the receiver’s superclass.
81    fn ip_superclass<'a>() -> Option<&'a Class> {
82        Self::m_class().superclass()
83    }
84
85    /* Identifying and Comparing Objects
86     */
87
88    /// Returns a Boolean value that indicates whether the receiver and a given object are equal.
89    fn m_is_equal(&self, object: &Self) -> bool {
90        unsafe { to_bool(msg_send![self.m_self(), isEqual: object]) }
91    }
92
93    /// Returns an integer that can be used as a table address in a hash table structure.
94    fn p_hash(&self) -> UInt {
95        unsafe { msg_send![self.m_self(), hash] }
96    }
97
98    /// Returns the receiver.
99    fn m_self(&self) -> id;
100
101    /* Testing Object Inheritance, Behavior, and Conformance
102     */
103
104    /// Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.
105    fn m_is_kind_of_class(&self, class: Class) -> bool {
106        unsafe { to_bool(msg_send![self.m_self(), isKindOfClass: class]) }
107    }
108
109    /// Returns a Boolean value that indicates whether the receiver is an instance of a given class.
110    fn m_is_member_of_class(&self, class: Class) -> bool {
111        unsafe { to_bool(msg_send![self.m_self(), isMemberOfClass: class]) }
112    }
113
114    /// Returns a Boolean value that indicates whether the receiver implements or inherits a method that can respond to a specified message.
115    fn m_responds_to_selector(&self, selector: Sel) -> bool {
116        unsafe { to_bool(msg_send![self.m_self(), respondsToSelector: selector]) }
117    }
118
119    /// Returns a Boolean value that indicates whether the receiver conforms to a given protocol.
120    fn m_conforms_to_protocol(&self, protocol: Protocol) -> bool {
121        unsafe { to_bool(msg_send![self.m_self(), conformsToProtocol: protocol]) }
122    }
123
124    /* Describing Objects
125     */
126
127    /// A textual representation of the receiver.
128    fn p_description(&self) -> NSString {
129        unsafe { NSString::from_id(msg_send![self.m_self(), description]) }
130    }
131
132    /// A textual representation of the receiver to use with a debugger.
133    fn p_debug_description(&self) -> NSString {
134        unsafe { NSString::from_id(msg_send![self.m_self(), debugDescription]) }
135    }
136
137    /* Sending Messages
138     */
139
140    /// Sends a specified message to the receiver and returns the result of the message.
141    fn m_perform_selector(&self, selector: Sel) -> id {
142        unsafe { msg_send![self.m_self(), performSelector: selector] }
143    }
144
145    /// Sends a message to the receiver with an object as the argument.
146    fn m_perform_selector_with_object(&self, selector: Sel, with_object: id) -> id {
147        unsafe { msg_send![self.m_self(), performSelector: selector withObject: with_object] }
148    }
149
150    /* Identifying Proxies
151     */
152
153    /// Returns a Boolean value that indicates whether the receiver does not descend from NSObject.
154    fn m_is_proxy(&self) -> bool {
155        unsafe { to_bool(msg_send![self.m_self(), isProxy]) }
156    }
157}
158
159/// Converting an Objective-C pointer to Object
160pub trait FromId: ToId {
161    /// Returns `Self` representation of the object.
162    ///
163    /// # Safety
164    ///
165    /// This function dereferences a raw pointer
166    unsafe fn from_id(ptr: id) -> Self;
167}
168
169/// Converting Object to an Objective-C pointer
170pub trait ToId {
171    /// Returns `id` representation of the object.
172    fn to_id(self) -> id;
173}