objc2-media-player: invalid message send to -[_MPMusicPlayerMediaItemProxy title]: method not found
The following code:
unsafe {
let player = MPMusicPlayerController::systemMusicPlayer();
let now_playing_item = player.nowPlayingItem();
match now_playing_item {
Some(now_playing_item) => {
let title = now_playing_item
.title()
.map(|ns_string| ns_string.to_string())
.unwrap_or("a song".to_string());
let artist = now_playing_item
.artist()
.map(|ns_string| ns_string.to_string())
.unwrap_or("an unknown artist".to_string());
println!("Now playing {title} by {artist}");
}
None => println!("There is nothing playing now"),
}
}
produces the following output:
thread 'main' panicked at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-media-player-0.2.2/src/generated/MPMediaItem.rs:232:1:
invalid message send to -[_MPMusicPlayerMediaItemProxy title]: method not found
stack backtrace:
0: 0x10057be2c - std::backtrace_rs::backtrace::libunwind::trace::he4f0a5f56afe8e37
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/../../backtrace/src/backtrace/libunwind.rs:105:5
1: 0x10057be2c - std::backtrace_rs::backtrace::trace_unsynchronized::habb302958e80f800
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x10057be2c - std::sys_common::backtrace::_print_fmt::h9819d35e2a5cda77
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:68:5
3: 0x10057be2c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1f3776e0b5c7517d
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:44:22
4: 0x100591bf4 - core::fmt::rt::Argument::fmt::h626862aa6242248a
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/fmt/rt.rs:165:63
5: 0x100591bf4 - core::fmt::write::heedef092c8c0962e
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/fmt/mod.rs:1157:21
6: 0x10057a02c - std::io::Write::write_fmt::h7178e8e2ea928914
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/io/mod.rs:1832:15
7: 0x10057bc84 - std::sys_common::backtrace::_print::ha0f584bc7bfb9d2b
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:47:5
8: 0x10057bc84 - std::sys_common::backtrace::print::h417292deb95532ed
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:34:9
9: 0x10057cde0 - std::panicking::default_hook::{{closure}}::h0cb68f1228c4613a
10: 0x10057cad4 - std::panicking::default_hook::h24535936bc1f51de
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:298:9
11: 0x10057d698 - std::panicking::rust_panic_with_hook::h5db4d2345b297bed
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:795:13
12: 0x10057d0c8 - std::panicking::begin_panic_handler::{{closure}}::h3fd558f09a0d5492
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:664:13
13: 0x10057c2b4 - std::sys_common::backtrace::__rust_end_short_backtrace::hfc76eebe1ce501b2
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:171:18
14: 0x10057ce38 - rust_begin_unwind
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:652:5
15: 0x10059d47c - core::panicking::panic_fmt::hc2b459a5bd3dce66
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:72:14
16: 0x10055581c - objc2::runtime::message_receiver::panic_verify::he9a1f6a7746f7dc5
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:346:5
17: 0x100555604 - objc2::runtime::message_receiver::msg_send_check_class::h8ce8854db5297ee6
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:334:5
18: 0x1005554e4 - objc2::runtime::message_receiver::msg_send_check::h2c95653d1055f9c6
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:311:5
19: 0x10054a238 - objc2::runtime::message_receiver::MessageReceiver::send_message::hcbf565f7dd70acd0
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/runtime/message_receiver.rs:426:13
20: 0x10054a10c - objc2::__macro_helpers::msg_send::MsgSend::send_message::h377ae34697ba117c
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/__macro_helpers/msg_send.rs:27:31
21: 0x100548b70 - <objc2::__macro_helpers::method_family::RetainSemantics<5_u8> as objc2::__macro_helpers::msg_send_id::MsgSendId<T,core::option::Option<objc2::rc::id::Retained<U>>>>::send_message_id::h50cf3642fa03ff6c
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/__macro_helpers/msg_send_id.rs:359:28
22: 0x100549df4 - objc2_media_player::generated::__MPMediaItem::MPMediaItem::title::hb51bb52498dfa77b
at /Users/valentinebriese/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc2-0.5.2/src/macros/extern_methods.rs:247:14
23: 0x10035cff4 - media_player_rich_presence::main::h33d9b7bb285513d1
at /Users/valentinebriese/Developer/media-player-rich-presence/src/main.rs:13:29
24: 0x10035e0fc - core::ops::function::FnOnce::call_once::ha9f785aeb04fc58b
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ops/function.rs:250:5
25: 0x10035e068 - std::sys_common::backtrace::__rust_begin_short_backtrace::h0e805b2a2dc04d23
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:155:18
26: 0x10035dcfc - std::rt::lang_start::{{closure}}::h88f7cff5978608f0
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/rt.rs:159:18
27: 0x100575d74 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h2f86a413382a979d
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ops/function.rs:284:13
28: 0x100575d74 - std::panicking::try::do_call::hd40c9eb4d233b111
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:559:40
29: 0x100575d74 - std::panicking::try::h13ac68ffa70c387b
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:523:19
30: 0x100575d74 - std::panic::catch_unwind::habea7b6fc986e966
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panic.rs:149:14
31: 0x100575d74 - std::rt::lang_start_internal::{{closure}}::h6b16436250c3cf62
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/rt.rs:141:48
32: 0x100575d74 - std::panicking::try::do_call::h9970b928a0b20951
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:559:40
33: 0x100575d74 - std::panicking::try::h4dfbe3cb4cc8f253
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:523:19
34: 0x100575d74 - std::panic::catch_unwind::hf6a5e1e8ce5a10f5
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panic.rs:149:14
35: 0x100575d74 - std::rt::lang_start_internal::hecc68fef83c8f44d
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/rt.rs:141:20
36: 0x10035dcc8 - std::rt::lang_start::hac1ec87399390c88
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/rt.rs:158:17
37: 0x10035d308 - _main
I am using objc2-media-player v0.2.2 with the features MPMediaEntity, MPMediaItem, and MPMusicPlayerController on macOS 15.1 Beta (24B5024e).
Thanks for the report - I remember seeing this asked on Matrix as well, the issue is that our debug assertion check is overly zealous about when methods exist. I think we need to use the Objective-C method instead of class_getInstanceMethod, but can't remember the details rn.
You can use something like the following to work around this issue in the meantime, apologies for the hazzle:
[profile.dev.package.objc2]
debug-assertions = false
the method check is also a problem for methods that are only available in newer macOS releases - crashing the debug app when running on older operating systems (see #11501 #11496) can we move the check behind a feature flag perhaps? or completely remove it?
the method check is also a problem for methods that are only available in newer macOS releases - crashing the debug app when running on older operating systems
While true, that's kinda the expected behaviour, even if this objc2 issue didn't exist, the application is gonna crash anyhow.
You must check the OS version and do something else when the API isn't available (can be done in the next release of objc2 with e.g. if objc2::available!(macos = 11.3) { ... }, otherwise you can query NSProcessInfo for the information).
See also the discussion on the wry issues: https://github.com/tauri-apps/wry/issues/1401, https://github.com/tauri-apps/wry/issues/1402.
can we move the check behind a feature flag perhaps? or completely remove it?
Both good options, not sure yet what I'll do (but I'll definitely do something to fix this before the next release).
@madsmtm that's true for API calls, but not for delegate methods (in this case you would just register a function for a class with a selector that simply do not exist and is not called by the operating system) to conditionally register the method in this case we'd need to support the version check in the method macros
Oh yeah, you're right!
I experimented with disabling encoding verification in extern_methods! only, but that was difficult to implement properly with the current design, and would only solve part of this issue anyhow.
Instead, I've added a feature in 155b5c75e87891dcecf98e5ce1ca8f2e802f3e7d to allow library authors to work around the issue. Once the next version is released, you can do the following instead:
[dependencies]
# NOTE: Disable encoding verification because XYZ
# See https://github.com/madsmtm/objc2/issues/645.
objc2 = { version = "0.3", features = ["disable-encoding-assertions"] }
@madsmtm disable-encoding-assertions is enabled however it seems that we're still seeing some crash for non-existing methods on older macOS (see https://github.com/tauri-apps/tauri/issues/11496#issuecomment-3109083618). Is it what disable-encoding-assertions what supposed to fix or is this assumption incorrect?
tauri/wry has the following line of code that seems to be problematic somehow:
https://github.com/tauri-apps/wry/blob/dev/src/wkwebview/class/wry_web_view_ui_delegate.rs#L64