insertDataforTableName returns wrong object type - objective-c

I'm building out some new functionality in my app which is essentially just old code copied for a new class type. Before it was creating and displaying vehicles, and now it's creating and displaying books, however it's not behaving as expected.
I want to persist the data, so here is the code which creates a new ManagedObject, which should return a pointer to the object:
vehicle = [[MyCoreDataManager sharedManager] insertDataforTableName:#"MyVehicle"];
This line returns an object of type MyVehicle, which is what I want. MyVehicle is a class which inherits from NSManagedObject and has its own methods which are immediately used after inserting.
Now I want to have the same exact arrangement, except with a MyBook object. However, when I run:
book = [[MyCoreDataManager sharedManager] insertDataforTableName:#"MyBook"];
The above line of code returns an object of type NSManagedObject, which is wrong because I can't access the MyBook methods because it's an NSManagedObject and not a MyBook. I even tried type casting, but it doesn't work. The fact that it is an NSManagedObject and not a MyBook is causing my app to crash with an unrecognized selector sent to instance exception because I am trying to call a method which is not recognized by the object at runtime. Your thoughts are appreciated.
My understanding of the problem is that somehow the MyBook class is not properly declared or has some subtle issue in its .h or .m file which is causing it not to link up at runtime. Or some kind of problem with the .xcdatamodeld entity definition.

Rob Mayoff was correct to ask:
Does the definition of the "MyBook" entity in the data model specify "MyBook" as its class?
Because in this case it did not. If you ever want to create a new entity in your data model, be sure to specify the actual class that it is associated with in the right hand toolbar. It's pretty easy to miss this step, if you ask me.

Related

Objective-C Passing Method Reference As Parameter

I've seen a lot of discussions NEAR this subject, but none that actually work in Xcode 5.x, especially using ARC. I have a simple problem:
I need to pass a method reference to a CreateButton method so that when the button is called it calls my custom function, and not some generic one.
I've tried using (SEL) type, but that doesn't work with ARC. I've tried using the &func method, but that claims I haven't declared the function yet.
So my need is:
Class A calls Class B and sends over the info to make a UIButton. Within that call, I want to send over the action:method in a reference. I'm sure this is done routinely, but I can't seem to find an iOS 7 / Xcode 5.x method of doing it. I've also reviewed the O'Reilly iOS 7 fundamentals and cookbook code and couldn't find this discussed anywhere.
Thanks for you help.
When I have to pass selectors around, I convert them to strings with NSStringFromSelector() and back to selectors with NSSelectorFromString().
Passing the strings around is a lot easier. You can store them in collections (arrays, dictionaries), serialize and unserialize them, and they will work naturally with ARC.
Example:
In your class A where you gather the information to create a button:
NSString *selectorString = NSStringFromSelector(#selector(yourActionMethodNameHere:));
// Gather more information needed by Class B here, then package
// it all up into a dictionary, for example
NSDictionary *buttonInfo = #{#"selectorString": selectorString, /* more stuff here */};
At this point, you can call your button-constructing method in Class B, passing along buttonInfo, which contains all the information that that helper method needs, including the selector. The method can convert the string back to a selector and use it like this:
SEL actionSelector = NSSelectorFromString(buttonInfo[#"selectorString"]);
// configure your button to use actionSelector here
You should be able to use SEL parameters? I know I have done before.
ARC might complain and give you a warning, but it won't fail to compile. It's simply a warning because it can't quite figure out what to do memory wise.
If you really can't get that to work though, another alternative would be to use a block, so you might call your method like
[objectA performMethodWithParam:paramA paramb:paramB completion:^{ ... do somethhing ... }];
Then in that method you can just call
completion();
Instead of actually calling a method.
Another alternative would be to use the delegate pattern. Create a #protocol defining a method such as classADidFinish then make class B implement that method. Then set the instance of classB as the delegate for your classA instance, and have it call that method when it's done.
Both of these approaches will stop ARC moaning at you.
But as I said, using SEL params should work fine. There is a way you can even get the compiler to stop showing you the warnings but it's a little ugly.

Setter method is odd, can someone explain

I'm taking a look at the developer library for iOS. A property called masterBirdSightingList was created with type NSMutableArray.Thats fine, in the implementation they added this peice of code
- (void)setMasterBirdSightingList:(NSMutableArray *)newList {
if (_masterBirdSightingList != newList) {
_masterBirdSightingList = [newList mutableCopy];
}
}
In order to
To implement a custom setter for the master list property ... (and) to override its default setter method to make sure that the new array remains mutable.
I'm not quite sure why this is fully necessary. Surely the array cannot suddenly change from a mutable array to something static. Is this method necessary?
Could you also help clarify whether the method setMasterBirdSightingList is called every time the masterBirdSightingList is set?
The tutorial I'm talking about is available here about halfway down the page.
Thank you
Could you also help clarify whether the method setMasterBirdSightingList is called every time the masterBirdSightingList is set?
Yes, it is - in Objective-C, property access is implemented using getter and setter methods. No exception. The dot notation is just syntactic sugar for - (T)foo and - (void)setFoo:(T)arg.
I'm not quite sure why this is fully necessary.
Because if you just declared a copy property, then upon setting the array, it would be sent the copy message, and that returns an immutable copy (in Cocoa [Touch], it's a common convention that copy returns an immutable copy, even if the original object was mutable.)
This is why explicitly sending mutableCopy to the argument is needed.

Titanium Properties API usage

I'm new to Titanium Properties API. I'm getting a weird error when using setObject() method.
Following is my code.
Titanium.App.Properties.setObject(view.idAttr, view);
Where view.idAttr is a string acting as a key for this property and view is a View type object. Upon calling above method, I get following message.
2012-09-14 17:47:25.947 SumMeUp[14033:4a03] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '[object TiUIView]' of class 'TiUIViewProxy'. Note that dictionaries and arrays in property lists must also contain only property values.
I couldn't understand this behavior. If anyone knows a solution to, please reply.
Thanx
setObject() is meant for objects only, not for views.
A object would be something you write yourself in JavaScript.
Even if it could, it would be bad behaviour of the app to store it in a property. Remember the property is being stored cross-session. So if you want something stored, store data there to generate the view later again, not the view itself. Also saves a lot of memory!

Calling a class method from another class in Objective-C (Cocoa)

I'm new to programming in Cocoa, so I'm still struggling to grasp some basic concepts.
What I want to do (as an example) is write an application with multiple NSTextFields. However, these NSTextFields need to be linked to separate classes. Additionally, each separate class needs to be able to get and set data from each other.
I tried to add methods to tackle this problem, to no avail. Let's say this is a method in the textbox's original class, and I want to call it from another class.
-(void)settextfield:(NSString*)stringy;
{
[TextField setStringValue:stringy];
}
Here's the calling code (we're calling this from another class, TestClass)...
-(IBAction)test:sender;
{
[BundleBrowseTextBox settextfield: #"Testy"];
}
Nothing happens. There's probably some obvious way to do this, but I haven't been able to unearth this via Google searches.
My mistake was that I was calling the class method instead of the instance... you can call the instance via IBOutlets and defining those outlets properly in Interface Builder.
You need to make sure the pointers you are using are not nil.
One odd/convenient thing about objC is that you can pass messages to nil and it won't crash.
If I'm right in assuming you're trying to set the text in an instance of BundleBrowseTextBox, you should call the settextfield: message on the instance name, rather than on the class name (if BundleBrowseTextBox IS the instance -- rather than the class -- you should really avoid capitalized instance names for clarity). i.e.:
-(IBAction)test:(id)sender;
{
// Assuming bbtBox is defined as an instance of BundleBrowseTextBox
[bbtBox settextfield: #"Testy"];
}
I believe you forgot your parameter type in your original post
this...
-(IBAction)test:sender;
{
[BundleBrowseTextBox settextfield: #"Testy"];
}
should be
-(IBAction)test:(id)sender;
{
[BundleBrowseTextBox settextfield: #"Testy"];
}
That aside if you understand the difference between class and instance as you say you do.
Then it would be nice if you would show us the rest of your implementation and interface.
The problem is probably not in the code snippets you showed us.

NSClassFromString returns nil

Why does NSClassFromString return nil ? As per the definition it has to return class name.
How should I take care to rectify this problem? I need to instantiate a class from string and call the method, which is in the class, using the instance created.
This is how my code looks like:
id myclass = [[NSClassFromString(#"Class_from_String") alloc] init];
[myclass method_from_class];
But the method_from_class function is not being called, control is not going into it. And my code is error free. Any idea how to solve this in Objective-C?
If you are trying to instantiate a class from a static library, you must add the "-ObjC" flag to the "Other Linker Flags" build setting.
The Documentation for the function says:
Return Value
The class object named by
aClassName, or nil if no class by that
name is currently loaded. If
aClassName is nil, returns nil.
An example of how this should be properly used is as follows:
Class dictionaryClass = NSClassFromString(#"NSMutableDictionary");
id object = [[dictionaryClass alloc] init];
[object setObject:#"Foo" forKey:#"Bar"];
It is possible that your class is not getting linked if this is the only reference to it.
I had a factory method to instantiate various types of subclass. The factory had a switch statement that went to the appropriate subclass and alloc'd and init'ed it. I noticed that all of the alloc/init statements were exactly the same, except for the name of the class. So I was able to eliminate the entire switch block using the NSClassFromString() function.
I ran into the same problem - the return was nil. This was because the class was not used elsewhere in the program, so it wasn't getting linked, so it could not be found at runtime.
You can solve this by including the following statement:
[MyClass class];
That defeats the whole purpose of what I was trying to accomplish, but it might be all you need.
This happened to me when I add an external file to the Xcode project. Adding the .m file to Build Phases > Compile Sources solve the problem.
You also need to make sure the class you are trying to instantiate is included in the project. If you added it later, you made need to click the checkbox next to the Target you are building.
Why not decomposing all these calls ? This way, you can check the values between the calls:
Class myclass = NSClassFromString(#"Class_from_String");
id obj = [[myclass alloc] init];
[obj method_from_class];
By the way, is method_from_class an instance method or a class method ? If it is the later, then you can directly call method_from_class on the myclass value:
[myclass method_from_class];
I also saw an oddity where adding the standard singleton code espoused by apple prevented the class from being loaded. The code was working as expected, then I added the singleton, and suddenly the NSClassFromString started returning nil. Commenting out the singleton code resulted in the NSClassFromString resolving the class correctly. I don't understand the interaction, but I think the singleton static var was somehow getting mangled to hide the class name...?