Skip to content

Commit e70519b

Browse files
committed
Move ClassBuilder example to the type itself
1 parent 506e0f6 commit e70519b

File tree

1 file changed

+110
-111
lines changed
  • crates/objc2/src/declare

1 file changed

+110
-111
lines changed

crates/objc2/src/declare/mod.rs

Lines changed: 110 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -3,117 +3,6 @@
33
//! Classes can be declared using the [`ClassBuilder`] struct. Instance
44
//! variables and methods can then be added before the class is ultimately
55
//! registered.
6-
//!
7-
//! **Note**: You likely don't need the dynamicism that this module provides!
8-
//! Consider using the [`declare_class!`][crate::declare_class] macro instead.
9-
//!
10-
//!
11-
//! ## Example
12-
//!
13-
//! The following example demonstrates declaring a class named `MyNumber` that
14-
//! has one ivar, a `u32` named `_number` and a few methods for constructor
15-
//! methods and methods for interfacing with the number (using interior
16-
//! mutability, as is common for Objective-C objects).
17-
//!
18-
//! ```
19-
//! use core::cell::Cell;
20-
//!
21-
//! use objc2::declare::ClassBuilder;
22-
//! use objc2::rc::Id;
23-
//! use objc2::runtime::{AnyClass, AnyObject, NSObject, Sel};
24-
//! use objc2::{sel, msg_send, msg_send_id, ClassType};
25-
//!
26-
//! fn register_class() -> &'static AnyClass {
27-
//! // Inherit from NSObject
28-
//! let mut builder = ClassBuilder::new("MyNumber", NSObject::class())
29-
//! .expect("a class with the name MyNumber likely already exists");
30-
//!
31-
//! // Add an instance variable of type `Cell<u32>`
32-
//! builder.add_ivar::<Cell<u32>>("_number");
33-
//!
34-
//! // Add an Objective-C method for initializing an instance with a number
35-
//! //
36-
//! // We "cheat" a bit here, and use `AnyObject` instead of `NSObject`,
37-
//! // since only the former is allowed to be a mutable receiver (which is
38-
//! // always safe in `init` methods, but not in others).
39-
//! unsafe extern "C" fn init_with_number(
40-
//! this: &mut AnyObject,
41-
//! _cmd: Sel,
42-
//! number: u32,
43-
//! ) -> Option<&mut AnyObject> {
44-
//! let this: Option<&mut AnyObject> = msg_send![super(this, NSObject::class()), init];
45-
//! this.map(|this| {
46-
//! // SAFETY: The ivar is added with the same type above
47-
//! this.set_ivar::<Cell<u32>>("_number", Cell::new(number));
48-
//! this
49-
//! })
50-
//! }
51-
//! unsafe {
52-
//! builder.add_method(
53-
//! sel!(initWithNumber:),
54-
//! init_with_number as unsafe extern "C" fn(_, _, _) -> _,
55-
//! );
56-
//! }
57-
//!
58-
//! // Add convenience method for getting a new instance with the number
59-
//! extern "C" fn with_number(
60-
//! cls: &AnyClass,
61-
//! _cmd: Sel,
62-
//! number: u32,
63-
//! ) -> *mut NSObject {
64-
//! let obj: Option<Id<NSObject>> = unsafe {
65-
//! msg_send_id![
66-
//! msg_send_id![cls, alloc],
67-
//! initWithNumber: number,
68-
//! ]
69-
//! };
70-
//! obj.map(Id::autorelease_return).unwrap_or(std::ptr::null_mut())
71-
//! }
72-
//! unsafe {
73-
//! builder.add_class_method(
74-
//! sel!(withNumber:),
75-
//! with_number as extern "C" fn(_, _, _) -> _,
76-
//! );
77-
//! }
78-
//!
79-
//! // Add an Objective-C method for setting the number
80-
//! extern "C" fn my_number_set(this: &NSObject, _cmd: Sel, number: u32) {
81-
//! // SAFETY: The ivar is added with the same type above
82-
//! unsafe { this.ivar::<Cell<u32>>("_number") }.set(number);
83-
//! }
84-
//! unsafe {
85-
//! builder.add_method(sel!(setNumber:), my_number_set as extern "C" fn(_, _, _));
86-
//! }
87-
//!
88-
//! // Add an Objective-C method for getting the number
89-
//! extern "C" fn my_number_get(this: &NSObject, _cmd: Sel) -> u32 {
90-
//! // SAFETY: The ivar is added with the same type above
91-
//! unsafe { this.ivar::<Cell<u32>>("_number") }.get()
92-
//! }
93-
//! unsafe {
94-
//! builder.add_method(sel!(number), my_number_get as extern "C" fn(_, _) -> _);
95-
//! }
96-
//!
97-
//! builder.register()
98-
//! }
99-
//!
100-
//! // Usage
101-
//!
102-
//! // Note: you should only do class registration once! This can be ensure
103-
//! // with `std::sync::Once` or the `once_cell` crate.
104-
//! let cls = register_class();
105-
//!
106-
//! let obj: Id<NSObject> = unsafe {
107-
//! msg_send_id![cls, withNumber: 42u32]
108-
//! };
109-
//!
110-
//! let n: u32 = unsafe { msg_send![&obj, number] };
111-
//! assert_eq!(n, 42);
112-
//!
113-
//! let _: () = unsafe { msg_send![&obj, setNumber: 12u32] };
114-
//! let n: u32 = unsafe { msg_send![&obj, number] };
115-
//! assert_eq!(n, 12);
116-
//! ```
1176
1187
mod ivar;
1198
mod ivar_bool;
@@ -335,6 +224,116 @@ impl<T> Log2Alignment for T {
335224

336225
/// A type for declaring a new class and adding new methods and ivars to it
337226
/// before registering it.
227+
///
228+
/// **Note**: You likely don't need the dynamicism that this provides!
229+
/// Consider using the [`declare_class!`][crate::declare_class] macro instead.
230+
///
231+
///
232+
/// # Example
233+
///
234+
/// Declare a class named `MyNumber` that has one ivar, a `u32` named `_number`
235+
/// and a few constructor methods and methods for interfacing with the number
236+
/// (using interior mutability, as is common for Objective-C objects).
237+
///
238+
/// ```
239+
/// use core::cell::Cell;
240+
///
241+
/// use objc2::declare::ClassBuilder;
242+
/// use objc2::rc::Id;
243+
/// use objc2::runtime::{AnyClass, AnyObject, NSObject, Sel};
244+
/// use objc2::{sel, msg_send, msg_send_id, ClassType};
245+
///
246+
/// fn register_class() -> &'static AnyClass {
247+
/// // Inherit from NSObject
248+
/// let mut builder = ClassBuilder::new("MyNumber", NSObject::class())
249+
/// .expect("a class with the name MyNumber likely already exists");
250+
///
251+
/// // Add an instance variable of type `Cell<u32>`
252+
/// builder.add_ivar::<Cell<u32>>("_number");
253+
///
254+
/// // Add an Objective-C method for initializing an instance with a number
255+
/// //
256+
/// // We "cheat" a bit here, and use `AnyObject` instead of `NSObject`,
257+
/// // since only the former is allowed to be a mutable receiver (which is
258+
/// // always safe in `init` methods, but not in others).
259+
/// unsafe extern "C" fn init_with_number(
260+
/// this: &mut AnyObject,
261+
/// _cmd: Sel,
262+
/// number: u32,
263+
/// ) -> Option<&mut AnyObject> {
264+
/// let this: Option<&mut AnyObject> = msg_send![super(this, NSObject::class()), init];
265+
/// this.map(|this| {
266+
/// // SAFETY: The ivar is added with the same type above
267+
/// this.set_ivar::<Cell<u32>>("_number", Cell::new(number));
268+
/// this
269+
/// })
270+
/// }
271+
/// unsafe {
272+
/// builder.add_method(
273+
/// sel!(initWithNumber:),
274+
/// init_with_number as unsafe extern "C" fn(_, _, _) -> _,
275+
/// );
276+
/// }
277+
///
278+
/// // Add convenience method for getting a new instance with the number
279+
/// extern "C" fn with_number(
280+
/// cls: &AnyClass,
281+
/// _cmd: Sel,
282+
/// number: u32,
283+
/// ) -> *mut NSObject {
284+
/// let obj: Option<Id<NSObject>> = unsafe {
285+
/// msg_send_id![
286+
/// msg_send_id![cls, alloc],
287+
/// initWithNumber: number,
288+
/// ]
289+
/// };
290+
/// obj.map(Id::autorelease_return).unwrap_or(std::ptr::null_mut())
291+
/// }
292+
/// unsafe {
293+
/// builder.add_class_method(
294+
/// sel!(withNumber:),
295+
/// with_number as extern "C" fn(_, _, _) -> _,
296+
/// );
297+
/// }
298+
///
299+
/// // Add an Objective-C method for setting the number
300+
/// extern "C" fn my_number_set(this: &NSObject, _cmd: Sel, number: u32) {
301+
/// // SAFETY: The ivar is added with the same type above
302+
/// unsafe { this.ivar::<Cell<u32>>("_number") }.set(number);
303+
/// }
304+
/// unsafe {
305+
/// builder.add_method(sel!(setNumber:), my_number_set as extern "C" fn(_, _, _));
306+
/// }
307+
///
308+
/// // Add an Objective-C method for getting the number
309+
/// extern "C" fn my_number_get(this: &NSObject, _cmd: Sel) -> u32 {
310+
/// // SAFETY: The ivar is added with the same type above
311+
/// unsafe { this.ivar::<Cell<u32>>("_number") }.get()
312+
/// }
313+
/// unsafe {
314+
/// builder.add_method(sel!(number), my_number_get as extern "C" fn(_, _) -> _);
315+
/// }
316+
///
317+
/// builder.register()
318+
/// }
319+
///
320+
/// // Usage
321+
///
322+
/// // Note: you should only do class registration once! This can be ensured
323+
/// // with `std::sync::Once` or the `once_cell` crate.
324+
/// let cls = register_class();
325+
///
326+
/// let obj: Id<NSObject> = unsafe {
327+
/// msg_send_id![cls, withNumber: 42u32]
328+
/// };
329+
///
330+
/// let n: u32 = unsafe { msg_send![&obj, number] };
331+
/// assert_eq!(n, 42);
332+
///
333+
/// let _: () = unsafe { msg_send![&obj, setNumber: 12u32] };
334+
/// let n: u32 = unsafe { msg_send![&obj, number] };
335+
/// assert_eq!(n, 12);
336+
/// ```
338337
#[derive(Debug)]
339338
pub struct ClassBuilder {
340339
// Note: Don't ever construct a &mut objc_class, since it is possible to

0 commit comments

Comments
 (0)