Importing (#import ...
) an Objective-C category adds the methods defined in that category to all instances of the class on which the category was defined. Other than with traits which can be mixed into classes selectively a category extends the class on which it was defined once and for all.
Also you can not create a standalone category and mix that into several different classes. A category is an extension for a specific class, similar as if you would add the methods to the class itself.
Traits are like java interfaces but with implementation. Wether a trait can be mixed into a class depends not on the classes name but on the methods the class provides. If a class has the methods a trait needs, the trait can be mixed into that class.
In many cases, people use inheritance to provide a trait to a class. For example think of a Pegasus. With multiple inheritance you might be tempted to say the Pegasus extends Horse and Bird because you've classified the Bird as an animal with wings.
However, Birds have other traits that Pegasi don't. For example, birds lay eggs, Pegasi have live birth. If inheritance is your only means of passing sharing traits then there's no way to exclude the egg laying trait from the Pegasus.
Some languages have opted to make traits an explicit construct within the language. Other's gently guide you in that direction by removing MI from the language. Either way, I can't think of a single case where I thought "Man I really need MI to do this properly".
Also let's discuss what inheritance REALLY is. When you inherit from a class, you take a dependency on that class, but also you have to support the contracts that class supports, both implicit and explicit.
Take the classic example of a square inheriting from a rectangle. The rectangle exposes a length and width property and also a getPerimeter and getArea method. The square would override length and width so that when one is set the other is set to match getPerimeter and getArea would work the same (2*length+2*width for perimeter and length*width for area).
There is a single test case that breaks if you substitute this implementation of a square for a rectangle.
var rectangle = new Square();
rectangle.length= 5;
rectangle.width= 6;
Assert.AreEqual(30, rectangle.GetArea());
//Square returns 36 because setting the width clobbers the length
It's tough enough to get things right with a single inheritance chain. It gets even worse when you add another to the mix.
The pitfalls I mentioned with the Pegasus in MI and the Rectangle/Square relationships are both the results of a inexperienced design for classes. Basically avoiding multiple inheritance is a way to help beginning developers avoid shooting themselves in the foot. Like all design principles, having discipline and training based on them allows you to in time discover when it's okay to break from them. See the Dreyfus Model of Skill Acquisition, at the Expert level, your intrinsic knowledge transcends reliance on maxims/principles. You can "feel" when a rule doesn't apply.
And I do agree that I somewhat cheated with a "real world" example of why MI is frowned upon.
Let's look at a UI framework. Specifically let's look at a few widgets that might at first brush look like they are simply a combination of two others. Like a ComboBox. A ComboBox is a TextBox that has a supporting DropDownList. I.e. I can type in a value, or I can select from a pre-ordained list of values. A naive approach would be to inherit the ComboBox from TextBox and DropDownList.
But your Textbox derives its value from what the user has typed. While the DDL gets its value from what the user selects. Who takes precedent? The DDL might have been designed to verify and reject any input that wasn't in its original list of values. Do we override that logic? That means we have to expose the internal logic for inheritors to override. Or worse, add logic to the base class that is only there in order to support a subclass (violating the Dependency Inversion Principle).
Avoiding MI helps you sidestep this pitfall altogether. And might lead to you extracting common, reusable traits of your UI widgets so that they can be applied as needed. An excellent example of this is the WPF Attached Property which allows a framework element in WPF to provide a property that another framework element can use without inheriting from the parent framework element.
For example a Grid is a layout panel in WPF and it has Column and Row attached properties that specify where a child element should be placed in the grid's arrangement. Without attached properties, if I want to arrange a Button within a Grid, the Button would have to derive from Grid so it could have access to the Column and Row properties.
Developers took this concept further and used attached properties as a way of componentizing behavior (for example here is my post on making a sortable GridView using attached properties written before WPF included a DataGrid). The approach has been recognized as a XAML Design Pattern called Attached Behaviors.
Hopefully this provided a little more insight on why Multiple Inheritance is typically frowned upon.
Best Answer
The diamond problem is the inability to decide which implementation of the method to choose. Scala solves this by defining which implementation to choose as part of the language specifications(read the part about Scala in this Wikipedia article).
Ofcourse, same order definition could also be used in class multiple inheritance, so why bother with traits?
The reason IMO is constructors. Constructors have several limitations that regular methods don't have - they can only be called once per object, they have to be called for each new object, and a child class' constructor must call it's parent's constructor as it's first instruction(most languages will do it implicitly for you if you don't need to pass parameters).
If B and C inherit A and D inherit B and C, and both B and C's constructors call A's constructor, than D's constructor will call A's constructor twice. Defining which implementations to choose like Scala did with methods won't work here because both B's and C's constructors must be called.
Traits avoid this problem since they don't have constructors.