Skip to content

Commit 8cdc355

Browse files
authored
Merge pull request #259 from madsmtm/classtype-name
Add `ClassType::NAME`
2 parents c712e0c + d294f2b commit 8cdc355

File tree

9 files changed

+50
-8
lines changed

9 files changed

+50
-8
lines changed

objc2/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1313
* Added `IvarDrop<T>` to allow storing complex `Drop` values in ivars
1414
(currently `rc::Id<T, O>`, `Box<T>`, `Option<rc::Id<T, O>>` or
1515
`Option<Box<T>>`).
16+
* **BREAKING**: Added required `ClassType::NAME` constant for statically
17+
determining the name of a specific class.
18+
* Allow directly specifying class name in declare_class! macro.
1619

1720
### Removed
1821
* **BREAKING**: `MaybeUninit` no longer implements `IvarType` directly; use
1922
`Ivar::write` instead.
2023

24+
2125
## 0.3.0-beta.2 - 2022-08-28
2226

2327
### Added

objc2/examples/class_with_lifetime.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@ impl<'a> MyObject<'a> {
7878

7979
unsafe impl<'a> ClassType for MyObject<'a> {
8080
type Super = NSObject;
81+
const NAME: &'static str = "MyObject";
8182

8283
fn class() -> &'static Class {
8384
// TODO: Use std::lazy::LazyCell
8485
static REGISTER_CLASS: Once = Once::new();
8586

8687
REGISTER_CLASS.call_once(|| {
8788
let superclass = NSObject::class();
88-
let mut builder = ClassBuilder::new("MyObject", superclass).unwrap();
89+
let mut builder = ClassBuilder::new(Self::NAME, superclass).unwrap();
8990

9091
builder.add_static_ivar::<NumberIvar<'a>>();
9192

objc2/examples/delegate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern "C" {}
1111

1212
#[cfg(all(feature = "apple", target_os = "macos"))]
1313
extern_class!(
14+
#[derive(Debug)]
1415
struct NSResponder;
1516

1617
unsafe impl ClassType for NSResponder {
@@ -20,6 +21,7 @@ extern_class!(
2021

2122
#[cfg(all(feature = "apple", target_os = "macos"))]
2223
declare_class!(
24+
#[derive(Debug)]
2325
struct CustomAppDelegate {
2426
pub ivar: u8,
2527
another_ivar: bool,
@@ -32,6 +34,7 @@ declare_class!(
3234
unsafe impl ClassType for CustomAppDelegate {
3335
#[inherits(NSObject)]
3436
type Super = NSResponder;
37+
const NAME: &'static str = "MyCustomAppDelegate";
3538
}
3639

3740
unsafe impl CustomAppDelegate {
@@ -100,6 +103,7 @@ impl CustomAppDelegate {
100103
fn main() {
101104
let delegate = CustomAppDelegate::new(42, true);
102105

106+
println!("{:?}", delegate);
103107
println!("{:?}", delegate.ivar);
104108
println!("{:?}", delegate.another_ivar);
105109
println!("{:?}", delegate.box_ivar);

objc2/src/class_type.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ use crate::Message;
1818
///
1919
/// The class returned by [`Self::class`] must be a subclass of the class that
2020
/// [`Self::Super`] represents, and `as_super`/`as_super_mut` must be
21-
/// implemented correctly.
21+
/// implemented correctly. Finally [`Self::NAME`] must be correct.
2222
///
2323
/// In pseudocode:
2424
/// ```ignore
2525
/// Self::class().superclass() == <Self::Super as ClassType>::class()
26+
/// Self::class().name() == Self::NAME
2627
/// ```
2728
///
2829
///
@@ -68,6 +69,9 @@ pub unsafe trait ClassType: Message {
6869
/// [`runtime::Object`]: crate::runtime::Object
6970
type Super: Message;
7071

72+
/// The name of the Objective-C class that this type represents.
73+
const NAME: &'static str;
74+
7175
/// Get a reference to the Objective-C class that this type represents.
7276
///
7377
/// May register the class with the runtime if it wasn't already.

objc2/src/foundation/object.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ __inner_extern_class! {
1717

1818
unsafe impl ClassType for NSObject {
1919
type Super = Object;
20+
const NAME: &'static str = "NSObject";
2021

2122
#[inline]
2223
fn class() -> &'static Class {

objc2/src/macros/declare_class.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,9 @@ macro_rules! __fn_args {
307307
/// Rust struct).
308308
///
309309
/// Note that the class name should be unique across the entire application!
310-
/// As a tip, you can declare the class with the desired unique name like
311-
/// `MyCrateCustomObject` using this macro, and then expose a renamed type
312-
/// alias like `pub type CustomObject = MyCrateCustomObject;` instead.
310+
/// You can declare the class with the desired unique name like
311+
/// `"MyCrateCustomObject"` by specifying it in `ClassType::NAME`, and then
312+
/// give the exposed type a different name like `CustomObject`.
313313
///
314314
/// The class is guaranteed to have been created and registered with the
315315
/// Objective-C runtime after the [`ClassType::class`] function has been
@@ -406,6 +406,8 @@ macro_rules! __fn_args {
406406
///
407407
/// unsafe impl ClassType for MyCustomObject {
408408
/// type Super = NSObject;
409+
/// // Optionally specify a different name
410+
/// // const NAME: &'static str = "MyCustomObject";
409411
/// }
410412
///
411413
/// unsafe impl MyCustomObject {
@@ -575,6 +577,8 @@ macro_rules! declare_class {
575577
unsafe impl ClassType for $for:ty {
576578
$(#[inherits($($inheritance_rest:ty),+)])?
577579
type Super = $superclass:ty;
580+
581+
$(const NAME: &'static str = $name_const:literal;)?
578582
}
579583

580584
$($methods:tt)*
@@ -612,6 +616,7 @@ macro_rules! declare_class {
612616
// Creation
613617
unsafe impl ClassType for $for {
614618
type Super = $superclass;
619+
const NAME: &'static str = $crate::__select_name!($name; $($name_const)?);
615620

616621
fn class() -> &'static $crate::runtime::Class {
617622
// TODO: Use `core::cell::LazyCell`
@@ -623,10 +628,10 @@ macro_rules! declare_class {
623628
let superclass = <$superclass as $crate::ClassType>::class();
624629
let err_str = concat!(
625630
"could not create new class ",
626-
stringify!($name),
631+
$crate::__select_name!($name; $($name_const)?),
627632
". Perhaps a class with that name already exists?",
628633
);
629-
let mut builder = $crate::declare::ClassBuilder::new(stringify!($name), superclass).expect(err_str);
634+
let mut builder = $crate::declare::ClassBuilder::new(Self::NAME, superclass).expect(err_str);
630635

631636
// Ivars
632637
$(
@@ -655,7 +660,7 @@ macro_rules! declare_class {
655660
});
656661

657662
// We just registered the class, so it should be available
658-
$crate::runtime::Class::get(stringify!($name)).unwrap()
663+
$crate::runtime::Class::get(Self::NAME).unwrap()
659664
}
660665

661666
#[inline]
@@ -689,6 +694,17 @@ macro_rules! declare_class {
689694
};
690695
}
691696

697+
#[doc(hidden)]
698+
#[macro_export]
699+
macro_rules! __select_name {
700+
($_name:ident; $name_const:literal) => {
701+
$name_const
702+
};
703+
($name:ident;) => {
704+
$crate::__macro_helpers::stringify!($name)
705+
};
706+
}
707+
692708
#[doc(hidden)]
693709
#[macro_export]
694710
macro_rules! __declare_class_methods {

objc2/src/macros/extern_class.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ macro_rules! __inner_extern_class {
254254

255255
unsafe impl<$($t_for $(: $b_for)?),*> ClassType for $for {
256256
type Super = $superclass;
257+
const NAME: &'static str = stringify!($name);
257258

258259
#[inline]
259260
fn class() -> &'static $crate::runtime::Class {

objc2/src/rc/test_object.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,13 @@ impl RcTestObject {
162162
unsafe { Id::new(msg_send![Self::class(), new]) }.unwrap()
163163
}
164164
}
165+
166+
#[cfg(test)]
167+
mod tests {
168+
use super::*;
169+
170+
#[test]
171+
fn ensure_declared_name() {
172+
assert_eq!(RcTestObject::class().name(), RcTestObject::NAME);
173+
}
174+
}

tests/src/test_object.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ unsafe impl RefEncode for MyTestObject {
2222

2323
unsafe impl ClassType for MyTestObject {
2424
type Super = NSObject;
25+
const NAME: &'static str = "MyTestObject";
2526

2627
fn class() -> &'static Class {
2728
class!(MyTestObject)

0 commit comments

Comments
 (0)