Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Id improvements #21

Merged
merged 16 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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