-
Notifications
You must be signed in to change notification settings - Fork 49
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
Question: How to add Rust properties to Objective-C objects? #194
Comments
I'm working on something that could enable part of this in #190 for simple ( Other types, e.g. |
Note that I've never used Xamarin before, and am not very well-versed in C#, a few code examples/ideas in pseudo-Rust of what you would like to achieve would help me a lot with understanding the use-case? Perhaps related upstream issue: SSheldon/rust-objc#56 |
Xamarin lets you write iOS and macOS apps entirely in C#. It cleverly exposes Objective-C types as C# types. It also provides ready-made bindings for the various Apple SDKs. Here's a 10-second example: using UIKit;
public class MyView : UIView {
UILabel label;
public override void ViewDidLoad() {
this.label = new UILabel();
this.label.Text = "Hello!";
this.AddSubView(this.label);
}
} Some features seen in this example:
I'll add that Xamarin is basically doing what objc/objc2 are attempting to do, but they went whole-hog and produced a gigantic ecosystem and ended up as a very successful startup that Microsoft eventually bought. But the core idea is just a set of bindings between Objective-C and C#. Now for some detail. C# objects live in their own heap, and their lifetime is controlled by the C# garbage collector. Objective-C types are owned by the Objective-C runtime. To connect the two, a C# UIView instance stores a pointer to the underlying Objective-C UIView and also |
Thanks for the example! I'll try to provide a similar example in Rust, assuming that:
use some_crate::uikit::{UIView, UILabel, UIResponder};
use objc2_foundation::{declare_class, NSObject};
use objc2::msg_send_id;
use objc2::rc::{Id, Shared};
declare_class! {
pub unsafe struct MyView: UIView, UIResponder, NSObject {
// Ideally the label should be created in `init`, then we wouldn't need an `Option` here
label: Option<Id<UILabel, Shared>>,
}
unsafe impl {
@sel(viewDidLoad)
fn view_did_load(&self) {
let mut label = UILabel::new();
label.set_text("Hello!");
self.label.set(Some(label.into_shared()));
// If taking `&mut self`, whether that is sound depends on further stuff
// *self.label = Some(label.into_shared());
self.add_sub_view(&self.label);
}
}
}
impl MyView {
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new] }
}
} The first thing you'll notice is that this is naturally not nearly as clean, since we're just a library, Rust and Objective-C are quite differnet, and Xamarin is a whole ecosystem with compiler plugins and whatnot. However, I think we're actually doing fairly good! Relating this to the features you pointed out:
use cacao::view::ViewDelegate;
pub struct MyViewDelegate {
label: Option<UILabel>,
}
impl ViewDelegate for MyViewDelegate {
fn did_load(&mut self) {
let mut label = UILabel::new();
label.set_text("Hello!");
*self.label = Some(label.into_shared());
self.add_sub_view(&self.label);
}
}
I think we'd probably want to allocate as much as possible in the Objective-C runtime, exactly to avoid such issues (the first example does this). |
Thanks.
Interesting.
|
Hmm... Maybe? I'm not really sure, it definitely could but I guess it depends on how
Yup, this should definitely be possible!
I'm pretty bad at using debuggers myself, so I don't know, depends on how they handle implementation details of the ivar (it works using |
TBH these are the things I'm more interested in getting right. |
Should clarify: within the method, autocomplete/intellisense could work somewhat. But importantly, they can't help you write the method signature, you have to do that yourself (hence the Hence it is something I won't tackle in
I think there's a lot of things, including fixing around 75% of all open
If you point me towards some resources for using debuggers in Rust (e.g. a GDB or LLDB setup) I could probably try it out and see how we fare, and check if I could improve the situation, but again, You can also try it out yourself, the |
Thanks for the responses, let you know if more questions come up. |
Re debugging ivars: I tried it out, it is not very good today, but can be improved with the unstable I would be willing to put in the work to do so, but that feature doesn't support LLDB (which macOS/XCode uses) yet, so the point is kinda moot until then. |
I'll close this issue in favour of #352, which tracks our debugger support. Feel free to re-open, or create a new issue if you have any more questions. (also, time has passed and we now have |
Hi, I'm looking for a way to use normal Rust fields within instances. This would allow Objective-C declared methods to work with rust fields per-instance. So far I haven't seen any examples of this.
FYI, I've used Xamarin iOS for a long time, and this is something that they have figured out really well. Briefly, each Objective-C instance is exposed to C# as a regular C# object. Under the covers, the C# object holds a pointer to the objective-C instance. The reverse is also true, although I haven't located the exact implementation, probably here.
Appreciate any thoughts/suggestions.
The text was updated successfully, but these errors were encountered: