Earlier quoted context omitted.
They're arguably competitors if you don't care about decompilation. But Binary Ninja has no decompiler and Hopper's was awful last I checked. Ghidra's decompiler seems as competent as Hex-Rays.
Binary Ninja has most of a decompiler and is expected to get the rest soon. Binary Ninja offers multiple views of the code, each with an API that gives you the same access that the GUI has. The different views vary in how much they are like assembly or C. Only that last step, real C code, is still missing. Those other views are quite good if your goal is to understand things, but less good if you were hoping to throw…
Anybody use SEH or MSVCRT exceptions on x86? Well, there are non-inlined functions that adjust the stack pointer dynamically there. Binary Ninja can't capture that. To be fair, it's unlikely IDA can either- but IDA has a heuristic (read- hack) that treats those functions specially. Result? SP-analysis for all callers generally fails, and Binja becomes convinced that arguments are being passed in eax and ebp.
Ah, but you can just patch the LLIL for calls to those functions to adjust the stack. Oh, no, you actually can't patch LLIL that way- it's immutable after the lifter creates it. Now, you can write your own architecture hook, and there you can be your own lifter- you can call the real lifter, see if it emits a LLIL_CALL to a function you recognize, and if so just emit the stack adjustment LLIL instead. Ah, heh, but you can't- you can't call the real lifter, because it doesn't emit LLIL, it adds LLIL to an existing function, and you can't remove that IL later- it's append-only. And you can't recognize functions easily, because the things passed into your GetInstructionLowLevelIL callback don't include a BinaryView pointer- the thing you'd need to find out anything at all about other functions. You can sort of, kind of, hack around this by calling about five other functions... for every CALL instruction in every function in the binary. This is, ah, less than performant.
Ever reversed a Win32 binary that uses the Win32 API a lot? I hope you like defining structs by hand, because OH BOY are you going to be defining a lot of structs to do anything useful. And you also get to define DWORD, LPDWORD, LPVOID, and every other annoying Windows typedef by hand. (You can be clever and use libclang hackery on the Windows SDK and automate some of this. But you'll have to do it yourself.)
Then there's stuff like type propagation only going forwards inside functions- sometimes. The GUI occasionally deciding that all basic blocks should be laid out in one small square, on top of each other. (You have to reanalyze the function to fix this.)
Mind you, I love Binary Ninja- I bought my own dang commercial license, and renewed it! It's getting better, fast... but it's got its warts.