Skip to content

Commit 6547b2c

Browse files
committed
Change protocol implementation syntax
This allows using types in the inheritance chain again
1 parent 18d0546 commit 6547b2c

File tree

3 files changed

+73
-18
lines changed

3 files changed

+73
-18
lines changed

objc2-foundation/examples/declaration.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ extern_class! {
1414
}
1515

1616
declare_class! {
17-
// For some reason, `NSApplicationDelegate` is not a "real" protocol we
18-
// can retrieve using `objc_getProtocol` - it seems it is created by
19-
// `clang` only when used in Objective-C...
20-
//
21-
// TODO: Investigate this!
2217
unsafe struct CustomAppDelegate: NSResponder, NSObject {
2318
pub ivar: u8,
2419
another_ivar: Bool,
@@ -57,6 +52,12 @@ declare_class! {
5752
println!("A class method!");
5853
}
5954
}
55+
56+
// For some reason, `NSApplicationDelegate` is not a "real" protocol we
57+
// can retrieve using `objc_getProtocol` - it seems it is created by
58+
// `clang` only when used in Objective-C...
59+
//
60+
// TODO: Investigate this!
6061
}
6162

6263
impl CustomAppDelegate {

objc2-foundation/src/macros.rs

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -752,15 +752,15 @@ macro_rules! __inner_declare_class {
752752
///
753753
/// # Examples
754754
///
755-
/// Declare a class `MyCustomObject` with a few instance variables and
756-
/// methods.
755+
/// Declare a class `MyCustomObject` that inherits `NSObject`, has a few
756+
/// instance variables and methods, and implements the `NSCopying` protocol.
757757
///
758758
/// ```
759759
/// use std::os::raw::c_int;
760760
/// use objc2::{msg_send, msg_send_bool, msg_send_id};
761761
/// use objc2::rc::{Id, Owned};
762762
/// use objc2::runtime::Bool;
763-
/// use objc2_foundation::{declare_class, NSObject};
763+
/// use objc2_foundation::{declare_class, NSCopying, NSObject, NSZone};
764764
/// #
765765
/// # #[cfg(feature = "gnustep-1-7")]
766766
/// # unsafe { objc2::__gnustep_hack::get_class_to_force_linkage() };
@@ -797,6 +797,15 @@ macro_rules! __inner_declare_class {
797797
/// Bool::YES
798798
/// }
799799
/// }
800+
///
801+
/// unsafe impl protocol NSCopying {
802+
/// @sel(copyWithZone:)
803+
/// fn copy_with_zone(&self, _zone: *const NSZone) -> *mut Self {
804+
/// let mut obj = Self::new(*self.foo);
805+
/// *obj.bar = *self.bar;
806+
/// obj.autorelease_return()
807+
/// }
808+
/// }
800809
/// }
801810
///
802811
/// impl MyCustomObject {
@@ -814,11 +823,19 @@ macro_rules! __inner_declare_class {
814823
/// }
815824
/// }
816825
///
826+
/// unsafe impl NSCopying for MyCustomObject {
827+
/// type Ownership = Owned;
828+
/// type Output = Self;
829+
/// }
830+
///
817831
/// fn main() {
818832
/// let obj = MyCustomObject::new(3);
819833
/// assert_eq!(*obj.foo, 3);
820834
/// assert_eq!(*obj.bar, 42);
835+
///
836+
/// let obj = obj.copy();
821837
/// assert_eq!(obj.get_foo(), 3);
838+
///
822839
/// assert!(MyCustomObject::my_class_method());
823840
/// }
824841
/// ```
@@ -828,7 +845,7 @@ macro_rules! __inner_declare_class {
828845
/// ```text
829846
/// #import <Foundation/Foundation.h>
830847
///
831-
/// @interface MyCustomObject: NSObject {
848+
/// @interface MyCustomObject: NSObject <NSCopying> {
832849
/// int bar;
833850
/// }
834851
///
@@ -861,20 +878,33 @@ macro_rules! __inner_declare_class {
861878
/// return YES;
862879
/// }
863880
///
881+
/// - (id)copyWithZone:(NSZone *)_zone {
882+
/// MyCustomObject* obj = [[MyCustomObject alloc] initWithFoo: self->foo];
883+
/// obj->bar = self->bar;
884+
/// return obj;
885+
/// }
886+
///
864887
/// @end
865888
/// ```
866889
#[macro_export]
867890
macro_rules! declare_class {
868891
{
869892
$(#[$m:meta])*
870-
unsafe $v:vis struct $name:ident: $inherits:ident $(, $inheritance_rest:ident)* $(<$($protocols:ident),+ $(,)?>)? {
893+
unsafe $v:vis struct $name:ident: $inherits:ty $(, $inheritance_rest:ty)* {
871894
$($ivar_v:vis $ivar:ident: $ivar_ty:ty,)*
872895
}
873896

874897
$(#[$impl_m:meta])*
875898
unsafe impl {
876899
$($methods:tt)*
877900
}
901+
902+
$(
903+
$(#[$impl_protocol_m:meta])*
904+
unsafe impl protocol $protocols:ident {
905+
$($protocol_methods:tt)*
906+
}
907+
),*
878908
} => {
879909
$(
880910
#[allow(non_camel_case_types)]
@@ -916,13 +946,6 @@ macro_rules! declare_class {
916946
let superclass = <$inherits>::class();
917947
let mut builder = ClassBuilder::new(stringify!($name), superclass).unwrap();
918948

919-
// Implement protocols
920-
$(
921-
$(
922-
builder.add_protocol(Protocol::get(stringify!($protocols)).unwrap());
923-
)+
924-
)?
925-
926949
$(
927950
builder.add_ivar::<<$ivar as $crate::objc2::declare::IvarType>::Type>(
928951
<$ivar as $crate::objc2::declare::IvarType>::NAME
@@ -940,6 +963,22 @@ macro_rules! declare_class {
940963
}
941964
}
942965

966+
// Implement protocols
967+
$(
968+
builder.add_protocol(Protocol::get(stringify!($protocols)).unwrap());
969+
970+
// SAFETY: Upheld by caller
971+
unsafe {
972+
$crate::__inner_declare_class! {
973+
@rewrite_methods
974+
@register_out
975+
@builder
976+
977+
$($protocol_methods)*
978+
}
979+
}
980+
)*
981+
943982
let _cls = builder.register();
944983
});
945984

@@ -958,6 +997,20 @@ macro_rules! declare_class {
958997
$($methods)*
959998
}
960999
}
1000+
1001+
// Protocol methods
1002+
$(
1003+
$(#[$impl_protocol_m])*
1004+
impl $name {
1005+
$crate::__inner_declare_class! {
1006+
@rewrite_methods
1007+
@method_out
1008+
@__builder
1009+
1010+
$($protocol_methods)*
1011+
}
1012+
}
1013+
)*
9611014
};
9621015
}
9631016

objc2-foundation/src/zone.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use objc2::{Encoding, RefEncode};
55
/// A type used to identify and manage memory zones.
66
///
77
/// Zones are ignored on all newer platforms, you should very rarely need to
8-
/// use this.
8+
/// use this, but may be useful if you need to implement `copyWithZone:` or
9+
/// `allocWithZone:`.
910
///
1011
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nszone?language=objc).
1112
#[derive(Debug)]

0 commit comments

Comments
 (0)