No known instance method for selector 'myWindowController' - macos

I have the following code in an app (which was written in 2011).
[[[[NSApp delegate] myWindowController] ...] ..];
Since upgrading to Xcode 6.1 This produces the following error:-
ARC Semantic Issue No known instance method for selector 'myWindowController'
Replacing this by the following generates no error.
id ttt = [NSApp delegate];
[[[ttt myWindowController] ...] ...];
PS Xcode seems to think the type is 'id<NSFileManagerDelegate>'
What is going on here?
I admit to being very rusty with Cocoa and Xcode. I am sure I could fix it by an appropriate cast, but this seems unnecessary, and I am attempting to understand why.
Further information
My AppDelegate.h
IBOutlet MyWindowController *myWindowController;
And AppDelegate.m
#synthesize myWindowController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
myWindowController = [[MyWindowController alloc] initWithWindowNibName:#"MainWindow"];

I resolved this with a cast (MyAppDelegate *).
[[[(MyAppDelegate *)[NSApp delegate] myWindowController] currentTvc] saveTableColumns]; // Xcode 6.1 error
I have concluded this is an Xcode 6.1 error as it seems to think [NSApp delegate] returns type id<NSFileManagerDelegate>

Make sure you are importing the header containing the MyWindowController #interface definition.
Cast your [NSApp delegate] with (MyWindowController *).
So your original line:
[[[[NSApp delegate] myWindowController] ...] ..];
should become:
[[[(MyAppDelegate *)[NSApp delegate] myWindowController] ...] ..];
You could also cast with (id), which is effectively what you are doing with the ttt variable, but that's cheating a little. Using the proper class when casting will give you better compiler checking as well as helping Xcode make accurate autocomplete suggestions (which is a good way to detect errors before they happen). Basically an object declared or cast as id means it can be an object of any class so any method that is defined in any class will be considered valid.
I'm having the same issue with Xcode 6.1 myself. I think the compiler changed somehow in Xcode 6.1. I wish I had an answer for why, myself. It doesn't instill a lot of confidence in Xcode 6.1.

Related

XCode analyzer not working

I am currently doing the CS193P lessons via iTunesU and the teacher mentioned the Build and Analyze option several times. He said that it was a nice tool and fun to play with.
So I tried, and noticed that it doesn't work, or that I don't understand how it should work (I think the last option).
I have a few memory leaks, and it is not warning me at all! I saw online that a blue thing should appear telling me it is a leak, but I don't see anything although I'm doing NSDictionary *dict = [[NSDictionary alloc] init];.
How is it supposed to work? From what I read on the internet I thought it should signal potential leaks. What am I doing wrong?
I'm using XCode 3.2.5.
Thanks.
Update:
This is a kind of bug, I think.
When I declare this in the interface like NSDictionary *dict; and initialize it (but nowhere deallocating it) it says nothing.
When I declare and initialize it in - (void) init and don't release it in there like:
- (void) init {
if(self = [super init])
NSDictionary *dict = [[NSDictionary alloc] init];
return self;
}
It does signal a leak. Why? Is this because of my settings? Is this a bug? If it is a bug, where and how should I report it?
It's giving you a warning because you're not deallocating it.
-(void)dealloc{
[super dealloc];
[dict dealloc];
}
It's not warning you because you should be able to release the objects as soon as you create them, and the analyzer goal is to alert you on possible leaks in your code.
You can either use autorelease, or you dealloc the object you create manually.
P.S., little curiosity: why are you using Xcode 3.2.5?
Don't know exactly if that version can, but in the latest versions of Xcode, when you run that tool, you are able to see WHAT object you are deallocating with the means of some arrows with explanation, something like
I just found out that a reboot and restart of Xcode will bring it back.

iOS Xcode 4 properties access

I switched to Xcode 4 recently and I don't really understand this new way to write accessors.
For example, in the application delegate class that is auto-generated when creating a new project, the window object is not declared in the #interface but just this way:
#property (nonatomic, retain) IBOutlet UIWindow *window;
Then, in the implementation file, we have the #synthesize window=_window;.
And in the functions, we have either self.window OR _window.
For example:
[self.window makeKeyAndVisible]; // in didFinishLaunchingWithOptions function
[_window release]; // in dealloc function
Can you explain me the difference, why there is nothing in the #interface, why we do #synthesize window=_window; instead of #synthesize window; and what is the difference between self.window and _window, I mean when do I have to call one more than the other?
I'm a bit lost, and feel like the new code I doing trying to do the same in not working properly...
Thanks!
"Why is there nothing in the #interface"
The runtime is synthesizing the ivar for you.
"Why do we do #synthesize window=_window;
This means that the window property will use an ivar named _window (by default the ivar name is the name of the property)
"What is the difference between self.window and _window?"
The former is using the window "getter" method (ie, foo = [self window]), and the latter is accessing the ivar directly.
"Why do I have to call one more than the other?"
It is generally considered unsafe to use accessor methods in your dealloc method, which means using the ivar is preferred.
This has nothing to do with Xcode 4. This is Objective-C 2.0 (which Xcode 4 uses by default when creating project templates).
I recommend reading the chapter on properties in The Objective-C Programming Language, that should make things much clearer
And doing things "the old way" will still work. You don't have to change everything overnight, simply remove the auto-created code if you don't like it, until you feel comfortable with the new syntax.

Manual binding in Cocoa

I have an ImageView which shows a lock, informing if an opened file is locked or not. I have 2 images for locked and unlocked cases. I want synchronize the displayed image with boolean value of my object representing an opened file.
To do this I want my ViewController to change the image in my ImageView depending on lock state of object. So both object and ViewController have a property "isLocked".
How can I synchronize them? It is easy in IB but I don't know how to do it programmatically. I tried in initialize method of my ViewController to use:
[ViewController bind:#"value" toObject:[ArrayController selection] withKeyPath:#"isLocked" options:nil];
But it doesn't work. In documentation it is said that I have to expose my binding before using it.
I try to put the following code in initializer method of my object:
[self exposeBinding:#"isLocked"];
But Xcode doesn't recognize this method.
Does somebody have experience with this kind of bindings establishing?
As #nick says, you want Key-Value-Observing.
[arrayController addObserver:self
forKeyPath:#"selection.isLocked"
options:NSKeyValueObservingOptionNew
context:#"this_context"]
Then when isLocked changes the -observeValueForKeyPath:ofObject:change:context: method that you have added to your viewController will be called (as long as you only manipulate isLocked in a KVC compliant way).
The options parameter lets you optionally tweak exactly what conditions will trigger the notification and what data is sent along with the notification. The context parameter is there to help you distinguish between notifications that you registered to receive and notifications your superclass registered to receive. It is optional.
Bindings seem like they might be useful to keep two values in sync. However, this is not what they do at all.
Yes, lots of things seem to give the impression that this is what they do, and there isn't much saying that this isn't what they do, also lots of people believe that this is what they do - but no, you cannot use them for this.
Only a handful of classes support bindings (they are listed here) and then, and this is the important bit, those classes only support binding their named bindings, and these bindings are not instance variables. eg NSTextField has a 'fontFamilyName' binding yet NSTextField does not have a 'fontFamilyName' property or instance variable, even a derived one. NSTextField does have a 'isBordered' property but not a binding - so you cannot bind 'isBordered'.
It does not mean anything to 'bind' an arbitrary property of an arbitrary Class.
Yes, you can bind two arbitrary values, the following code works just fine:
#import <Cocoa/Cocoa.h>
#interface SomeObject : NSObject
#property (retain,nonatomic) id someValue;
#end
#implementation SomeObject
#end
int main()
{
SomeObject *source=[SomeObject new];
SomeObject *target=[SomeObject new];
[target bind:#"someValue" toObject:source withKeyPath:#"someValue" options:0];
[source bind:#"someValue" toObject:target withKeyPath:#"someValue" options:0];
[source setSomeValue:#(42)];
NSLog(#"target: %#",[target someValue]);
[target setSomeValue:#(22)];
NSLog(#"source: %#",[source someValue]);
return 0;
}
As far as I can tell, the problem is the bit [ArrayController selection]. The first problem is that ArrayController is (or should be) a class, and getting the class's selection is probably pointless. The other problem is that even if this were an instance, you would be binding to the selection at the time of the call, which is almost certainly not what you want. You want to track the current selection as it changes.
So what you want is probably something like the following:
[myViewController bind:#"value" toObject:myArrayController withKeyPath:#"selection.isLocked" options:nil];

How do i get rid of '-managedObjectContext' not found in protocol(s)

my app runs on iPhone device and also in simulator. Everythings seems fine, but i see a compiler warning during build. I hate to deliver code thats not completely correct so i need to get rid of this warning. The compiler warning is:
newsReaderController.m:24: warning: '-managedObjectContext' not found in protocol(s)
The Code is:
- (void)viewDidLoad {
[super viewDidLoad];
//CORE DATA
if (managedObjectContext == nil) {
managedObjectContext = [[[UIApplication sharedApplication] delegate] managedObjectContext];
}
}
The managedObjectContext for CoreData operation is set up in App Delegate. Core Data Framework is importet and the app works like a charm.
any hint for me ? I'm working with objective-C for some weeks now but there seems to be something new to learn every day :)
Since -[UIApplication delegate] returns an object of type id<UIApplicationDelegate>, the compiler is complaining that no -managedObjectContext method exists in that one protocol. It's there, and you know it's there, so you can solve this issue by casting to your delegate's specific type (MyAppDelegate or whatever it may be called), or by casting to id:
id appDelegate = (id)[[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];

How to change an NSTableView's selection without using deprecated methods

I have the Apress "Learn Cocoa" book (published in 2010 BTW) and I am getting a deprecation error on one of the lines. The code is:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.villain = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Lex Luthor", kName, #"Smallville", kLastKnownLocation, [NSDate date], kLastSeenDate, #"Superman", kSwornEnemy, #"Revenge", kPrimaryMotivation, [NSArray arrayWithObjects:#"Intellect", #"Leadership", nil], kPowers, #"Superhero Action", kPowerSource, [NSNumber numberWithInt:9], kEvilness, [NSImage imageNamed:#"NSUser"], kMugshot, #"", kNotes, nil];
self.villains = [NSMutableArray arrayWithObject:self.villain];
[villainsTableView reloadData];
[villainsTableView selectRow:0 byExtendingSelection:NO];
[self updateDetailViews];
}
I am getting the error on the 2nd to last line and I don't know exactly what that line is intending to do.
The replacement for the deprecated method would look like this:
[villainsTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
The documentation tells you what that message does and what the replacement is.
In XCode you can place the mousecursor above the symbol you want to know something about. While placing the mousecursor above this symbol (i.e. NSString), hold down the ALT-Key and doubleclick. This will open up a context sensitive documentation. All deprecated methods and symbols are marked red there. Mostly the new replacement is documented next to the old one. In the new xcode, a popup-window will appear. The doc will be opened by clicking the "notebook"-icon at the border of the box.
i.e. for NSString you will find:
– initWithCString: Deprecated in iOS 2.0
+ stringWithCString:encoding:
With an educated guess you will choose "+ stringWithCString:encoding:"
Apple almost adds new functionality which is a logical augmentation of the old stuff, so you don't need to google hard, but watch into the method summary of the related doc.

Resources