Skip to content

Commit

Permalink
Merge pull request #21 from madsmtm/id-improvements
Browse files Browse the repository at this point in the history
A bunch of `Id` improvements
  • Loading branch information
madsmtm authored Sep 9, 2021
2 parents 39c7ac1 + baff6f9 commit 923b893
Show file tree
Hide file tree
Showing 25 changed files with 930 additions and 757 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ members = [
"objc2_exception",
"objc2_foundation",
"objc2_foundation_derive",
"objc2_id",
"objc2_sys",
"objc2_test_utils",
]
Expand Down
26 changes: 14 additions & 12 deletions objc2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,33 @@ unsafe {

The utilities of the `rc` module provide ARC-like semantics for working with
Objective-C's reference counted objects in Rust.
A `StrongPtr` retains an object and releases the object when dropped.
A `WeakPtr` will not retain the object, but can be upgraded to a `StrongPtr`
and safely fails if the object has been deallocated.

An `Id` retains an object and releases the object when dropped.
A `WeakId` will not retain the object, but can be upgraded to an `Id` and
safely fails if the object has been deallocated.

```rust , no_run
use objc2::{class, msg_send};
use objc2::rc::{autoreleasepool, StrongPtr};
use objc2::rc::{autoreleasepool, Id, Shared, WeakId};
use objc2::runtime::Object;

// StrongPtr will release the object when dropped
let obj = unsafe {
StrongPtr::new(msg_send![class!(NSObject), new])
// Id will release the object when dropped
let obj: Id<Object, Shared> = unsafe {
Id::new(msg_send![class!(NSObject), new])
};

// Cloning retains the object an additional time
let cloned = obj.clone();
autoreleasepool(|_| {
// Autorelease consumes the StrongPtr, but won't
autoreleasepool(|pool| {
// Autorelease consumes the Id, but won't
// actually release until the end of an autoreleasepool
cloned.autorelease();
let obj_ref: &Object = cloned.autorelease(pool);
});

// Weak references won't retain the object
let weak = obj.weak();
let weak = WeakId::new(&obj);
drop(obj);
assert!(weak.load().is_null());
assert!(weak.load().is_none());
```

## Declaring classes
Expand Down
14 changes: 8 additions & 6 deletions objc2/examples/introspection.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use objc2::rc::StrongPtr;
use core::ptr::NonNull;

use objc2::rc::{Id, Owned};
use objc2::runtime::{Class, Object};
use objc2::{class, msg_send, sel, Encode};

Expand All @@ -14,15 +16,15 @@ fn main() {
}

// Allocate an instance
let obj = unsafe {
let obj: Id<Object, Owned> = unsafe {
let obj: *mut Object = msg_send![cls, alloc];
let obj: *mut Object = msg_send![obj, init];
StrongPtr::new(obj)
let obj: NonNull<Object> = msg_send![obj, init];
Id::new(obj)
};
println!("NSObject address: {:p}", obj);

// Access an ivar of the object
let isa: *const Class = unsafe { *(**obj).get_ivar("isa") };
let isa: *const Class = unsafe { *obj.get_ivar("isa") };
println!("NSObject isa: {:?}", isa);

// Inspect a method of the class
Expand All @@ -33,6 +35,6 @@ fn main() {
assert!(*hash_return == usize::ENCODING);

// Invoke a method on the object
let hash: usize = unsafe { msg_send![*obj, hash] };
let hash: usize = unsafe { msg_send![obj, hash] };
println!("NSObject hash: {}", hash);
}
9 changes: 6 additions & 3 deletions objc2/src/exception.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::rc::StrongPtr;
use core::ptr::NonNull;

use crate::rc::Id;
use crate::runtime::Object;
use objc2_exception::{r#try, Exception};

// Comment copied from `objc2_exception`

Expand All @@ -18,6 +21,6 @@ use crate::runtime::Object;
/// undefined behaviour until `C-unwind` is stabilized, see [RFC-2945].
///
/// [RFC-2945]: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html
pub unsafe fn catch_exception<R>(closure: impl FnOnce() -> R) -> Result<R, StrongPtr> {
objc2_exception::r#try(closure).map_err(|exception| StrongPtr::new(exception as *mut Object))
pub unsafe fn catch_exception<R>(closure: impl FnOnce() -> R) -> Result<R, Id<Exception>> {
r#try(closure).map_err(|e| Id::new(NonNull::new(e).unwrap()))
}
4 changes: 3 additions & 1 deletion objc2/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ macro_rules! sel {
Sends a message to an object.
The first argument can be any type that dereferences to a type that implements
[`Message`], like a reference, a pointer, or an `objc2_id::Id` to an object.
[`Message`], like a reference, a pointer, or an [`rc::Id`] to an
object.
The syntax is similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.
[`Message`]: crate::Message
[`rc::Id`]: crate::rc::Id
# Panics
Expand Down
7 changes: 0 additions & 7 deletions objc2/src/rc/autorelease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ use crate::runtime::{objc_autoreleasePoolPop, objc_autoreleasePoolPush};
///
/// And this is not [`Sync`], since you can only autorelease a reference to a
/// pool on the current thread.
///
/// See [the clang documentation][clang-arc] and [the apple article on memory
/// management][memory-mgmt] for more information on automatic reference
/// counting.
///
/// [clang-arc]: https://clang.llvm.org/docs/AutomaticReferenceCounting.html
/// [memory-mgmt]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
pub struct AutoreleasePool {
context: *mut c_void,
}
Expand Down
Loading

0 comments on commit 923b893

Please sign in to comment.