Skip to content

Commit

Permalink
Go through ObjectiveC.modulemap and take information from there
Browse files Browse the repository at this point in the history
Also look at libobjc.A.tdb and ObjectiveC.apinotes.

This commit includes a fix to make NSObjectProtocol::isEqual take a
nullable argument, which is what the APINotes declare it as (and which
is important for users that want to override it, as they must handle
nullability).
  • Loading branch information
madsmtm committed Dec 17, 2024
1 parent e71b884 commit 0ba5c79
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 11 deletions.
2 changes: 2 additions & 0 deletions crates/objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
`Hash`, instead of guarding them behind `T: Message`.
* Prevented main thread only classes created using `declare_class!` from
automatically implementing the auto traits `Send` and `Sync`.
* **BREAKING**: Fixed the signature of `NSObjectProtocol::isEqual` to take a
nullable argument.


## 0.5.2 - 2024-05-21
Expand Down
10 changes: 8 additions & 2 deletions crates/objc2/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,8 +1142,10 @@ unsafe impl RefEncode for AnyProtocol {
/// Note that protocols are objects, though sending messages to them is
/// officially deprecated.
//
// SAFETY: Protocols are objects internally, and are returned as `Retained` in
// various places in Foundation.
// SAFETY: Protocols are NSObjects internally (and somewhat publicly, see e.g.
// `objc/Protocol.h`), and are returned as `Retained` in various places in
// Foundation. But that's considered deprecated, so we don't implement
// ClassType for them (even though the "Protocol" class exists).
unsafe impl Message for AnyProtocol {}

impl fmt::Debug for AnyProtocol {
Expand Down Expand Up @@ -1221,6 +1223,10 @@ unsafe impl RefEncode for AnyObject {
// SAFETY: This is technically slightly wrong, not all objects implement the
// standard memory management methods. But not having this impl would be too
// restrictive, so we'll live with it.
//
// NOTE: AnyObject actually resolves to the class "Object" internally, but we
// don't want to expose that publicly, so we only implement Message here, not
// ClassType.
unsafe impl Message for AnyObject {}

impl AnyObject {
Expand Down
21 changes: 14 additions & 7 deletions crates/objc2/src/runtime/nsobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ use crate::{
/// This represents the [`NSObject` class][cls]. The name "NSObject" also
/// refers to a protocol, see [`NSObjectProtocol`] for that.
///
/// Since this class is only available with the `Foundation` framework,
/// `objc2` links to it for you.
///
/// This is exported under `objc2_foundation::NSObject`, you probably
/// want to use that path instead.
/// This class has been defined in `objc` since macOS 10.8, but is also
/// re-exported under `objc2_foundation::NSObject`, you might want to use that
/// path instead.
///
/// [cls]: https://developer.apple.com/documentation/objectivec/nsobject?language=objc
#[repr(C)]
Expand Down Expand Up @@ -131,7 +129,7 @@ pub unsafe trait NSObjectProtocol {
///
/// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418795-isequal?language=objc
#[doc(alias = "isEqual:")]
fn isEqual(&self, other: &AnyObject) -> bool
fn isEqual(&self, other: Option<&AnyObject>) -> bool
where
Self: Sized + Message,
{
Expand Down Expand Up @@ -259,6 +257,8 @@ pub unsafe trait NSObjectProtocol {
/// let desc: Retained<NSString> = unsafe { Retained::cast_unchecked(obj.description()) };
/// println!("{desc:?}");
/// ```
//
// Only safe to override if the user-provided return type is NSString.
fn description(&self) -> Retained<NSObject>
where
Self: Sized + Message,
Expand All @@ -276,6 +276,8 @@ pub unsafe trait NSObjectProtocol {
/// same value as `description`. Override either to provide custom object
/// descriptions.
// optional, introduced in macOS 10.8
//
// Only safe to override if the user-provided return type is NSString.
fn debugDescription(&self) -> Retained<NSObject>
where
Self: Sized + Message,
Expand Down Expand Up @@ -334,6 +336,8 @@ pub unsafe trait NSObjectProtocol {
{
unsafe { msg_send![self, retainCount] }
}

// retain, release and autorelease below to this protocol.
}

crate::__inner_extern_protocol!(
Expand Down Expand Up @@ -416,6 +420,9 @@ extern_methods!(
}

// TODO: `methodForSelector:`, but deprecated, showing how you should do without?

// Don't expose load, initialize and dealloc, since these should never
// be called by the user.
}
);

Expand All @@ -430,7 +437,7 @@ impl PartialEq for NSObject {
#[inline]
#[doc(alias = "isEqual:")]
fn eq(&self, other: &Self) -> bool {
self.isEqual(other)
self.isEqual(Some(other))
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/objc2/src/runtime/nsproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl PartialEq for NSProxy {
#[inline]
#[doc(alias = "isEqual:")]
fn eq(&self, other: &Self) -> bool {
self.isEqual(other)
self.isEqual(Some(other))
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/objc2/src/runtime/protocol_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl<P: ?Sized + NSObjectProtocol> PartialEq for ProtocolObject<P> {
#[inline]
#[doc(alias = "isEqual:")]
fn eq(&self, other: &Self) -> bool {
self.isEqual(&other.inner)
self.isEqual(Some(&other.inner))
}
}

Expand Down

0 comments on commit 0ba5c79

Please sign in to comment.