instance variable in NSManagedObject class acts like a class variable? - nsmanagedobject

IOS 5 only, with ARC. In my Core Data model class:
// Planet.h //
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Planet : NSManagedObject
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSNumber *diameter_km;
#property (nonatomic, retain) NSNumber *mass_kg;
-(void) setVisited:(BOOL)flag;
-(BOOL) isVisited;
#end
// Planet.m //
 
//#import "Planet.h"
#implementation Planet
 
#dynamic name;
#dynamic diameter_km;
#dynamic mass_kg;
 
BOOL visitedByHumans;       // not a core data entity; just an ivar
 
-(void)setVisited:(BOOL)flag {
    visitedByHumans = flag;
}
-(BOOL)isVisited {
    return visitedByHumans;
}
 
#end
I use MagicalRecord to create "Venus" and "Mars". In my view controller, I use labels and buttons to test the above. Testing shows that when I "visit" Mars, Venus also becomes visited. If I switch the ivar visitedByHumans into a non-Core-Data property, it works as expected. So I'm no longer 'stuck', but I want to understand the ivar thing.

vistedByHumans is not actually an ivar, but a global variable of your subclass Planet. So, any and every "planet" instance will appear to be visited regardless of which instance is actually visited. If you want to make it an actual ivar, you need to add a #property to your #interface much like name, diameter_km, and mass_kg (although, those three of course were generated for your models). e.g.:
#property (nonatomic,assign,getter=isVisited) BOOL visited;
and in your implementation:
#synthesize visited=visitedByHumans;
or just
#synthensize visited;
Since you appear to be using those methods (visited and setVisited:) anyhow, and not really directly accessing visitedByHumans.
Also, be sure to remove the line of code
BOOL visitedByHumans;
and the two method definitions isVisited and setVisited:. They will be generated for you when you #synthesize'd them.

It's impossible to be sure based on the information you've presented. Your description doesn't match the code-- despite what you say, visitedByHumans is most definitely not an instance variable in that code. This then makes me wonder what the code looked like back before you switched it away from using Core Data for visitedByHumans. Basically, you explain that the code wasn't working right when you were using Core Data, but then present entirely different code that doesn't actually use Core Data. I don't know what you were doing when you were trying to use Core Data for this property so I can't tell what you might have been doing wrong. If that declaration of visitedByHumans was in the code at that time, it was almost certainly screwing things up for you. Likewise, if you had setters in a managed object subclass that didn't call super's implementation, you'd get bad results. But if you want to know why your Core Data code wasn't working, paste that code, not some completely different code. Don't make people guess what you're up to when you ask for help.

Related

How to mock a CQ5 Page object containing a cq5 tag

I have a method on which I'd like to run a JUnit test. I'm mocking the cq5 page using JMockit.
My test method looks like this
#Mocked
Page page;
#Mocked
PageManager pageManager;
Tag testTag = pageManager.createTag("someID","someTitle","someDescription");//i've left out the try catch for brevety
System.out.println(testTag.getTitle()); // always null here
public void testSomeMethod() {
new Expectations() {
// variables declared here are mocked by default
{
page.getProperties();
propertyMap.put("cq:tags", testTag);
returns(new ValueMapDecorator(propertyMap));
}
};
String propertyValue = methodToBeTested(page);
Assert.assertEquals(propertyValue, "someTitle");
}
And the actual method to be tested does this :-
public static String getTopic(Page page) {
String topic = null;
Tag[] tags = page.getTags();
System.out.println(tags.size()); // returns 0 when I run the test.
for (int i = 0; i < tags.length; i++) {
Tag tag = tags[i];
topic = tag.getTitle();
}
}
return topic;
}
This always returns null when I run the test; however the method to be tested works correctly in the real scenario.
I suspect I'm not setting/mocking PageManager correctly, and consequently, my testTag is null
How do I mock this correctly to get the output I'm looking for?
You're getting to this testing from the wrong side. The way mocks (usually - I've never worked with jmockit specifically) work is, you create a blank object that acts as an impostor. This impostor is not a true PageManager - it only acts as one, and introduces himself as one whenever asked. When someone asks that impostor to do something (like calling it's method), the impostor does not know what to do, so it does nothing and returns null. However, you can tell the impostor how to behave in certain situations. Namely, you can tell it what to do when a method is called.
In your case, you don't need to create actual tags to test that method - you only need to mock a page object that, when asked for it's tags, will return an array containing a mocked tag which, in turn, when asked for it's title, will respond with the title you actually want to use in your test.
I don't know jmockit, so I cannot provide any code snippet. This, however, is a general question not strictly connected to CQ5/AEM
You may not be able to find any 'setter' methods for all objects you are trying to mock and this is anyways not the correct approach to mock.
The best way as mentioned by is to use mocked pages. You can use the Expectations class (mockit.Expectations) to mock the values to be returned by certain methods in the object.
See this example of mocking a 'SlingHttpServletRequest' object in a MockedClass class.
#Test
public void testMethod(#Mocked final SlingHttpServletRequest request){
String indicator ;
new Expectations() {
{
request.getParameter("archive");
returns("true");
}
};
indicator = OriginalClass.originalMethod(request);
Assert.assertEquals(indicator, "true");
}
In a similar way, you can mock other objects and their desired values.
I have answered the same question here: https://forums.adobe.com/thread/2536290
I ran into the same issue. in order to resolve Tags, they must exists under /content/cq:tags/your/tag or /etc/tags (legacy).
The Page#getTags implementation makes a call to TagManager#getTags which in turn tries to resolve the actual tag resource in the repo. Since you are testing in an AEM context, you have to load these tags in the appropriate location for the MockTagManager to resolve them.
What this means is that you need to load your tags into the AEM test context just like you've loaded your resources (via json).
Take a look at the aem-mock TagManager impl here: wcm-io-testing/MockTagManager.java at develop · wcm-io/wcm-io-testing · GitHub start with the resolve method and debug your way to figure out where you need to add those tags.

Assign super to variable in AS3

I have this:
public class Base {
public function whoAmI() {
trace("base");
}
}
public class Extended extends Base {
public function Extended() {
this.whoAmI() //prints extended
super.whoAmI() //prints base
var test = super;
test.whoAmI() //prints extended
}
public override function whoAmI() {
trace("extended");
}
}
The problem is when I do var test = super, it seems like this is assigned to test instead of super.
Is it possible to do the assignment so that test.whoAmI() prints "base"?
Edit: In the comments it is being said that using super in the way I propose would break overriding. I don't think that's the case. The way I am thinking of it, super could be used the same way as this. I understand that is not the way super is implemented, but using it that way would not break overriding as people are claiming. So for example the same way this is possible:
var test = this;
test.whoAmI();
This should be possible:
var test = super;
super.whoAmI();
It is obviously the choice of the language implementer to not do things this way, and I don't understand the reason why. It doesn't break things, but I guess it does make them more complicated.
I am not suggesting type-casting this to the super class. Obviously that wouldn't work.
You are thinking of "this" and "super" as 2 different instances, 2 different things but they in fact point to the same object (obviously) so at the end it's always "this". Using super is just a special keyword that allows the instance to point to the overrided definitions up the inheritance chain, it does not point to a different object. So "super" does correctly its job, it points to the instance and allow you each time you use it to access overrided definitions and that's it. There's of course no point on trying to store that keyword in a variable since in that case it just return correctly the instance it points to which is always "this".
It's simply a case of misunderstood inheritance principle and I've seen it before, super is mistaken for some kind of instance wrapper up the inheriatnce chain around the object "this" while it's in fact and always the same object.
No, this is not possible.
If this were possible, then overriding methods wouldn't be possible!
For example, take this function...
public function test(a:Object):void {
trace(a.toString());
}
You'd only get [object Object] back if your idea was how things worked.
Ok I understand what you mean your question is more about language definition and specification.
Look at this exemple in c# that explain how you can manage more precisely overriding in c# :
http://www.dotnet-tricks.com/Tutorial/csharp/U33Y020413-Understanding-virtual,-override-and-new-keyword-in-C
But
let's explain a litlle how it's work.
when you extend a class, it's like if you create an object composed of all the object in the inheritance tree so if B extends A and C extends B you have two objects like this:
(B+A) and (C+B+A) with hierarchy between each other B->A and C->B->A. Super is just a way to ascend in the hierachy.
When you cast a C in A for example. In memory you always have an object (C+B+A) but interpreted as A. When you override you just say that a method in child has an higher priority than in parent.
You can try downcasting this manually to any of your class's predecessors. The pointer will still be equal to this but the methods called will use the class table of the class used to downcast.
public class Extended extends Base {
public function Extended() {
this.whoAmI() //prints extended
super.whoAmI() //prints base
var test:Base = this;
test.whoAmI() //should print base
}
public override function whoAmI() {
trace("extended");
}
}
Should your Base extend something, which methods are known or the superclass is dynamic, and there is code that adds methods to prototype of a class, you might use such a downcast to call a superclass's method that might not be there at compile time, but make sure you first call hasOwnProperty in case of a dynamic class to determine whether a method or property exists.

Coding a custom navigationItem.rightBarButtonItem once and having it reused in both UITableViewControllers and UIViewControllers?

I have successfully added a rightBarButtonItem to my navigationBar, but I would prefer to only have the code to do so show up once rather than once per type of ViewController. Here's my current setup:
-->TVC
|
NVC--->TVC--->TVC--->VC
So far I've subclassed UITableViewController and moved my code for adding the button into my subclass. All 3 of my TableViewControllers are set to that subclass and it works perfectly.
However now I need my lone ViewController to also show the button, but I don't know how to accomplish this without duplicating the code from my TVC subclass. Is subclassing the right answer or do I need a different approach?
Edits:
#CarlVeazey - Sure, I call it from the viewDidLoad function.
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"BETA" style:UIBarButtonItemStylePlain target:self action:#selector(betaPressed)];
Do a pull-up refactor into a UIViewController category. If your project already has one, just add this code there, otherwise press cmd-N in Xcode to create a new file and choose "Objective-C Category" and enter UIViewController in the "Category On" field.
In the interface add this method declaration:
- (void)onfConfigureRightNavigationBarButton;
And in the implementation add this method implementation:
- (void)onfConfigureRightNavigationBarButton
{
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"BETA"
style:UIBarButtonItemStylePlain
target:self
action:#selector(betaPressed)];
}
Then in any UIViewController subclass you can import your category header and call this method. You may also wish to add to your category an empty implementation of betaPressed:.
BTW, ONF is the prefix I use for non-work coding so use whatever prefix already is in your project, or none at all if you're not concerned with category name collisions.

Need Delegate in Razor with two Parameters

I have the following syntax in a .cshtml page:
#cell(<Class object>)
And is defined like this in the header:
Func<dynamic, object> cell =
#<........>;
How can I define the cell Func so that I can send it an int parameter, like this?
#cell(<Class object>, intNum)
Thanks
You have 2 ways:
first one, the clever way: make a class type that contains at least 2 properties, the original Class and the int number that you need. and then access them.
second one:
the proper way of razor delegate:
http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx
http://blogs.msdn.com/b/simonince/archive/2012/01/26/templated-razor-delegates-combined-with-partial-views.aspx
Use delegates is not necessary unless you need to pass html code to an htmlhelper extension.
Maybe you need to use a #helper function and conserve html inside a cshtml file.

How do i create a UITextView in main UIView from a UIButton Within UIPopover?

I'm trying to create a UITextView in my Main UIViewController when a UIControlEventTouchUpInside happens with my UIButton which is in a UIPopoverController.
I tried to use a delegate protocol to allow my button to be referenced within the Main viewcontroller.m but I don't think I have been doing it right. I will also mention I've created the UIButton and UITextField programmatically in a UIView subclass for the UIPopover.
The view controller that you display in the UIPopoverController should look something like this:
#interface MyViewControllerForPopover : UIViewController
#property (weak) UIViewController *viewControllerInWhichCreateTheTextField;
...
#end
Meaning that you could keep a weak reference to the view controller in which you want to add the text field. The button you generated in this MyViewControllerForPopover could do something like:
- (void)createTextViewInConnectedViewController:(id)sender {
UITextField *myTextField = ...;
[self.viewControllerInWhichCreateTheTextView.view addSubview:myTextField];
}
The key concept is that you want to have a weak reference (to avoid retain cycle) to the view controller you wish to alter. Even better if that view controller has a method to actually add the text field itself. Hope it helps!