MR_SHORTHAND does not work - ios

I use MagicalRecords but by some reason MR_SHORTHAND does not work for me.
I have added these lines below to Prefix.pch
#define MR_SHORTHAND
#import "CoreData+MagicalRecord.h"
In case when app calls + createEntity method the app terminates due unrecognized selector. But if I write MR_createEntity everything works fine.
Team *team = [Team MR_createEntity]; // This line works
but
Team *team = [Team createEntity]; // This line does not work
with reason: '+[Team createEntity]: unrecognized selector sent to class 0x74b8c'

I know we haven't announced it publicly prior to this answer, but we've decided to deprecate shorthand support, and remove it in the upcoming MR3 release.
Shorthand support is an interesting idea and feature, but it is not something we want to maintain. We would rather focus our efforts on getting the data centric part of MagicalRecord to be as solid and reusable as possible.
That said, you're certainly welcome to fix it yourself and submit a patch to the older branch of MagicalRecord. Some things to look at are:
Make sure the shorthand selectors are included, and add new ones if they are not present
Make sure you've used the MagicalRecord class once prior to this call. All the shorthand support is initialized in the class initializer method.
If you're using Cocoapods, you may need to update your pod spec reference to 'MagicalRecord/Shorthand'

According to the official guide https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Installing-MagicalRecord.md
You have to call
[MagicalRecord enableShorthandMethods];

the above error means the core data stack is not initialized yet.
you should add [MagicalRecord setupCoreDataStackWithStoreNamed:dbName]; in app delegate before [self.window makeKeyAndVisible];
because if you have called [Team createEntity]; in your root VC [self.window makeKeyAndVisible]; make the view be loaded and visible, but still app has not reached the next line to setup core data stack

Related

convert non-ARC to ARC

I was working on non-ARC based project which was very old, and added some new UIViewControllers which are based on ARC (can do it by setting -fobjc-arc flag in build phase).
As being mixed use of ARC and non-ARC, sometimes memory leak occurs because forgotten to release somewhere in non-ARC code, and switching from here to there can cause this.
Thus, I have decided to convert non-ARC project to ARC project and do it by following;
Convert non-ARC to ARC project without recreate it
And just removed dealloc, viewDidUnload function contents by removing release or autorelease related things.
After successfully done it, it seems okay to working on but sometimes crashes like message sent to deallocated instance.
I could find what is the reason of that crashes and can be fixed.
What I want to know from here is;
When converting, is there any specific guide or rules to do this rather than simple remove of release, autorelease related statements?
Any input will be very appreciated!
Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects.
Refer this url :-
https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
As mentioned above, in ARC, we need not add release and retain methods since that will be taken care by the compiler. Actually, the underlying process of Objective-C is still the same. It uses the retain and release operations internally making it easier for the developer to code without worrying about these operations, which will reduce both the amount of code written and the possibility of memory leaks.
There was another principle called garbage collection, which is used in Mac OS-X along with MRR, but since its deprecation in OS-X Mountain Lion, it has not been discussed along with MRR. Also, iOS objects never had garbage collection feature. And with ARC, there is no use of garbage collection in OS-X too.
Here is a simple ARC example. Note this won't work on online compiler since it does not support ARC.
#import <Foundation/Foundation.h>
#interface SampleClass:NSObject
- (void)sampleMethod;
#end
#implementation SampleClass
- (void)sampleMethod
{
NSLog(#"Hello, World! \n");
}
- (void)dealloc
{
NSLog(#"Object deallocated");
}
#end
int main()
{
/* my first program in Objective-C */
#autoreleasepool{
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
sampleClass = nil;
}
return 0;
}
get the following output...
demo :- Hello, World!
demo :- Object deallocated
xcode could do the most of the conversion alone. in most cases its enough to remove this statements. you need to check the property declarations #property(nonatomic, weak/strong/copy).
Here is a litte tutorial:
https://objectpartners.com/2013/07/17/converting-an-ios-project-to-use-arc-automatic-reference-counting/
Just follow the things
STEP 1: Go to Project Target and click Build Phases
STEP 2: Click Compile Sources.Where you can see the all the .m files
STEP 3: Double click that,white box will appear with cursor.
STEP 4: give -fno-objc-arc in where the non arc files are.

cannot stub class method with OCMock 2.1+ in Xcode 5.0

I know that OCMock version 2.1+ supports stubbing class methods out of the box. But for some reason it's not working with me. To make sure I isolated the problem, I simply cloned the example OCMock project (which is clearly marked as version 2.2.1) and simply added this inside testMasterViewControllerDeletesItemsFromTableView:
id detailViewMock = [OCMockObject mockForClass:[DetailViewController class]];
[[[detailViewMock stub] andReturn:#"hello"] helloWorld];
in DetailViewController.h I added:
+ (NSString *)helloWorld;
and DetailViewController.m:
+ (NSString *)helloWorld {
return #"hello world";
}
But I keep on getting the error:
*** -[NSProxy doesNotRecognize Selector:helloWorld] called!
to see a demo of the problem please clone this repo to see what's going on.
That should work just fine. I just tried in a project of mine which uses XCTest on Xcode5, and that code passed.
I would 1) make sure you are using the latest version of OCMock (which is 2.2.1 right now; I think there are some fixes for both class methods and Xcode5 in the newer versions), and 2) make sure your DetailViewController class is linked in the runtime (i.e. part of the correct target) correctly.
In looking at your project, your DetailViewController class is part of both the main application, and the test target. With Xcode5, it appears this means that two copies of the class get compiled and are present in the runtime, with code in the app calling one copy, and code in the test case calling the other. This used to be a linker error (duplicate symbols), but for better or worse, the linker now appears to silently allow two copies of the same class (with the same name) to exist in the ObjC runtime. OCMock, using dynamic lookup, finds the first one (the one compiled into the app), but the test case is directly linked to the second copy (the one compiled into the test bundle). So... OCMock is not actually mocking the class you think it is.
You can see this, just for grins, by verifying as part of the test case that [DetailViewController class] will not equal NSClassFromString(#"DetailViewController") (the first is directly linked, the second is dynamic).
To fix this properly, in the "Target Memberships" for DetailViewController.m, just uncheck the test target. This way there is only one copy of the class in the runtime, and things work like you'd expect. The test bundle gets loaded into the main application, so all of the main application's classes should be available to the bundle without having to directly compile them into the bundle. Classes should only be part of one of the two targets, not both (this has always been the case).
Could you show the code you are testing?
This works:
#interface DetailViewController : UIViewController
+ (NSString *) helloWorld;
#end
#implementation DetailViewController
+ (NSString *)helloWorld
{
return #"hello world";
}
#end
The test:
- (void) test__stubbing_a_class_method
{
id mockDetailViewController = [OCMockObject mockForClass:[DetailViewController class]];
[[[mockDetailViewController stub] andReturn:#"hello"] helloWorld];
STAssertEqualObjects([DetailViewController helloWorld], #"hello", nil);
}
Looking at your sample project:
You should not be compiling DetailViewController.m in your test target.
You should not have any references to OCMock in your primary target.
I removed all reference to OCMock from both projects, then just included OCMock from source and the test passes just fine. I think you probably just have some environmental conflicts that are causing your problem.
Although Carl Lindberg's answer is the correct one, I figured i'd summarize what we discussed in his answer's comments here:
The problem was simply that I was using an out dated version of
OCMock. The reason I got there was b/c the instructions on the
ocmock page simply referred me to grab the
iOS example off their github account and copy over the OCMock
library (They even instructed to use the same directory structure).
It turns out that the library in their example is over 2 years
old!!.
To remedy that, simply run the build.rb script on shell like so:
ruby build.rb. This will give you an up to date libOCMock.a library, which you can simply plug back in to your project, and Voila! it's all done!
just use
id detailViewMock = [OCMockObject niceMockForClass:[DetailViewController class]];

Unrecognized Selector Sent to To instance for UIButton+AFNetworking.h (UIImageView+AFNetworking too)

i am trying to integrate the AFNetworking class for UIButton (i am calling a profile page and am loading in the avatar for the user async'd).
https://gist.github.com/dpettigrew/2925847
Xcode error: -[UIRoundedRectButton setImageWithURL:placeholderImage:forState:]: unrecognized selector sent to instance 0xd2431a0
I tried to follow this example (https://github.com/luisespinoza/ActivityIndicatorImageURL) and i'm getting the same error on the UIImageView too.
I verified that all the files are copied into xcode and including in the build phases area. The thing that doesn't make sense though, is when i hold command and click the method, where i'm calling it, it jumps to the right method no problem. Any ideas? how do i get xcode to find the method on run time?
self->avatar is the UIButton linked via an IBOutlet in my storyboard.
UIImage *imageTemp = [UIImage imageNamed:#"default_avatar.png"];
[self->avatar setImageWithURL:url placeholderImage:imageTemp forState:UIControlStateNormal];
Edit
Also note that i do have the following in my .h
#import "UIButton+AFNetworking.h"
#import "UIImageView+AFNetworking.h"
Edit: My previous answer is totally wrong, because subclass inherit methods of the superclass. I answered like it were a class cluster.
Are you using AFNetworking as a static library? If so, you have to add the -ObjC linker flag.
Look the accepter solution here:(Objective-C categories in static library)
I am not sure what the issue is but here is a sample project that uses both the UIButton and the UIImageView categories
http://numberpress.co/personal/UIButtonAFNetworkingTest.zip
if you come across this and can't ifgure it out, i recommend trying UIButton+WebCache.h
unfortunately i had issues with this too (the cache was far too strict, only looking at the URL and payload size, which were always the same so it never got reset, so i just don't use the cache part)

ios - 'autorelease is unavailable' errors and 'ARC forbids explicit message send of autorelease' errors

I had an app that was working just fine. And then I tried to embed the navigation controller into a tabbarcontroller and next thing I know I started getting these errors during compiling.
Would anyone know why these happen? Did some setting get unchecked or checked by accident?
Thanks,
Alex
Seems your previously working code did not use ARC, now you tried to embed it into code which uses ARC ... Refactor your code using "Edit->Convert->Convert to Object-C ARC"
ARC is enabled per translation -- every compiled source file and everything it sees via inclusion must abide by the ARC or MRC. And yes, the modes can coexist (i.e. you can have ARC on for some files, but not all and the libraries you link to can use either).
You have two modes:
ARC
The expression [obj autorelease] is forbidden. ARC will add it for you (unless you have unusual reference counting sequences).
Under typical scenarios, you can just write:
// a method which returns an autoreleased object
- (NSArray *)something
{
return [[NSArray alloc] initWithObjects:…YOUR_OBJECTS…];
}
and then ARC will add the autorelease for you.
But if you write:
- (NSArray *)something
{
return [[[NSArray alloc] initWithObjects:…YOUR_OBJECTS…] autorelease];
}
in ARC, it will be a compile error (like the one in your title).
MRC
And this is the MRC form:
- (NSArray *)something
{
return [[[NSArray alloc] initWithObjects:…YOUR_OBJECTS…] autorelease];
}
Your project probably uses ARC by default (i.e. it is defined in an xcconfig, at the project level, or at the target level), though you have added a source file which was written for MRC.
Since the file is either compiled as ARC, you can either remove the autorelease message or disable ARC for the single file.
The errors are on the new code?
In that case I think your projects is ARC-enabled and when you tried to embed the UINavigationController you inserted some non-ARC code.
Did you change the compiler?
LLVM compiler introduces ARC. If you were developing a non-ARC project, maybe you just compiled with LLVM and that broke your code.
Try refactoring the code. Check this.

Why are my NSManagedObject subclass methods not being recognized?

I've (heavily) subclassed NSManagedObject for a project. It worked in the original project seamlessly and without any effort.
I copied those files over to a new project, manually adding the appropriate CoreData classes to the new data model.
Unfortunately, I'm having 'issues'. For some reason, the methods of the subclass in question are being ignored. The exact same code between the two projects, but I'm suddenly getting an unrecognized selector issue.
NSFetchRequest *blockRequest=[[NSFetchRequest alloc] init];
NSEntityDescription *blockDesc=[NSEntityDescription entityForName:#"AdBlock"
inManagedObjectContext:context];
[blockRequest setEntity:blockDesc];
AdBlock *curBlock=[adBlocks objectAtIndex:blockIndex];
adBlocks=[context executeFetchRequest:blockRequest error:nil];
for (AdBlock *block in adBlocks) {
[block initAdBlock];//Crashes with unrecognized selector
}
I've checked, and the appropriate .m files got added to the compiler build phase. The code was quite literally copy&paste and is identical between the two projects -- source works, destination doesn't.
I've noticed that I don't explicitly tell the context that it should return the subclass type, but that wasn't an issue in the old project, so why should it be an issue in the new one?
When something like this happens to me, there's two things I try. The first thing I do is make sure I properly #imported the NSManagedObject subclass (I forget that way more often than I should), but as you said you copied and pasted, I don't think that is your problem. The second thing I try is to rebuild the NSManagedObjects by going to File>New>File then NSManagedObject Subclass then selecting the NSManagedObjects that I changed something in. I would recommend rebuilding all of them in your case. See if that works. It may not, but it's an easy place to start.
Make sure you check your model and ensure that you've change the class names in the inspector. Otherwise, they'll return as NSManagedObjects no matter what. And use mogenerator so you don't have to worry about regenerating your classes.
I know this question is stale, but maybe someone searching will find this helpful.
I've been using categories to add additional functions to NSManagedObject subclasses. This allows me to use the XCode command to generate the class definition without destroying any of the custom logic. Ron mentions this in a comment on the selected answer - just thought it would be worth calling attention to as I find it's a pretty slick solution.

Resources