Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

Doc Block posted:

Maybe NSNumberFormatter?

Thanks. I'd run across that last night, but I guess I was a bit tired and didn't actually find the section of the documentation I needed to read. NSNumberFormatter takes care of my problem perfectly, I believe.

Adbot
ADBOT LOVES YOU

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

carry on then posted:

Are there any good guides (in the Apple documentation or otherwise) for creating GUI applications for OS X, especially with advice on how to structure the controllers, how to get controllers talking to each other, and other design patterns?

Check out the Cocoa Design Patterns section of the Cocoa Fundamentals Guide for a start.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

stray posted:

I've got this big dictionary in a plist of addresses, phone numbers, etc. I'm accessing it through a standard UINavigationController / UITableViewController setup, but there might be modes of the app where we want to open that data from whatever view we're in.

So essentially: how do I create a view controller that takes/requires a parameter to instantiate correctly?

Subclass UIViewController, make a new init method (and label it the designated initializer so others know), then override UIViewController's designated initializer to call yours. So:

code:
@interface MyViewController : UIViewController

// Designated initializer.
- (id)initWithAddresses:(NSDictionary *)addresses;

@end
code:
@implementation MyViewController

- (id)initWithAddresses:(NSDictionary *)addresses
{
  self = [super initWithNibName:nil bundle:nil];
  if (self) {
    // ...
  }
  return self;
}

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle
{
  return [self initWithAddresses:nil];
}
And if you really don't want your view controller instantiated without the dictionary, throw an exception in your overridden -initWithNibName:bundle:.

take boat
Jul 8, 2006
boat: TAKEN
Is there a way to get higher-resolution thumbnails from ALAssets? On the iPad, the thumbnails I get by the standard method are 75x75.

Apple's Photo app seems to have thumbnails at up to 110x110 -- are they doing their own thumbnailing?

I can do my own thumbnailing as well, but I'd like to avoid that if possible.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I got curious tonight and looked around for a bit to see if there's any consensus about how to implement -dealloc. The questions I was curious about were:

1. Is there any point to niling out instance variables after releasing them?
2. Can I use accessors (e.g. self.something = nil) instead of releasing directly?

The only relevant Apple documentation I came across says

Apple posted:

Typically in a dealloc method you should release object instance variables directly (rather than invoking a set accessor and passing nil as the parameter) ... If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method

Which contains incorrect information (you can in fact directly access a synthesized instance variable and have been able to for awhile). I also came across a blog post from last year by Jeff LaMarche, Daniel Jalkut's response, and a StackOverflow question from Dave DeLong. In case any of those names are unfamiliar, they're all people who should know the answer, yet everything I've linked seems to say something different.

So I guess I'm wondering if anyone has come across a definitive explanation for what works best and why?

Sewer Adventure
Aug 25, 2004

pokeyman posted:

1. Is there any point to niling out instance variables after releasing them?

Yes because anything that tries to access them after they are released will cause a crash if they are not nil

quote:

2. Can I use accessors (e.g. self.something = nil) instead of releasing directly?

Yes I prefer to do this but it is slightly more computationally intensive because you are calling a method rather than just setting a variable. But this can be good if you are using a custom setter e.g. to add KVO or NSNotification observers.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Please file a bug against the documentation; that's old information.

The only reason that the recommendation is to release ivars directly instead of using a setter is to avoid problems from subclasses/swizzlers that screw with the setter — well, that and it's a message-send faster. In practice, this is usually only a problem for frameworks/libraries, not for user code.

Generally, after an ivar is released during dealloc, you should never access it. If you actually manage that correctly, there's no reason to nil the ivar out, and not doing so saves you some insignificant amount of time.† Contrariwise, the reason to nil the ivar out is to be defensive: you're trying to avoid crashes by hoping that any code which accesses it will behave reasonably with a null value. But avoiding such crashes is not an unmitigated blessing, because avoiding the crash usually means not running code that you probably wanted to run, which means you get subtler bugs. There's no perfectly agreed-upon answer here, but I do have a recommendation: if you're really interesting in provoking crashes on invalid behavior, scribble nonsense into your variables (like (id) 0x12121212) instead of leaving them with their just-released values.

† I don't mean this dismissively. It often happens that profiling your code shows something basically flat. That's good, but it doesn't mean you can't improve — it just means that all the easy work is done (or you have a major cost center that's been repeatedly inlined and thus distributed over a lot of different functions). The only way forward is to pick at a hundred tiny things, and the best way to do that is to not need to because you paid attention to small-scale performance when you wrote the code in the first place.

lord funk
Feb 16, 2004

Is Xcode 4.1 more stable than 4.0.2? I've been sitting at 4.0.1 for a while and I'm reluctant to upgrade (for no reason other than preventing headaches), but it is crashing constantly.

Small White Dragon
Nov 23, 2007

No relation.

lord funk posted:

Is Xcode 4.1 more stable than 4.0.2? I've been sitting at 4.0.1 for a while and I'm reluctant to upgrade (for no reason other than preventing headaches), but it is crashing constantly.
Yes, Xcode 4.0 crashed a lot on me, but 4.1 does not so much.

That said, I have run into a bug where after a few hours of modify/compile/run in Xcode 4.1, Lion will fail to launch new processes. :o But I'm sure if that's Xcode's fault, or the OS's.

lord funk
Feb 16, 2004

Is this what you mean?



Because I'm getting that about 60% of the time I hit run. Full on hang, force quit, reopen, clean, build, run. And this is after insignificant or no changes to the code.

Small White Dragon
Nov 23, 2007

No relation.
When it happens, I can't do things like open new terminal windows. I usually end up restarting the machine.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

rjmccall posted:

Please file a bug against the documentation; that's old information.

Done.

quote:

dealloc words

Thanks for clearing that up. I kind of wish there was a constantly-updated quick reference list to things like this. "Do this in dealloc, here's why"; "yes, you should assign to self in an init method"; and so on.

lord funk
Feb 16, 2004

lord funk posted:



Because I'm getting that about 60% of the time I hit run. Full on hang, force quit, reopen, clean, build, run. And this is after insignificant or no changes to the code.

I upgraded to Xcode 4.0.2 (still on Snow Leopard), and it is still happening. It is getting absolutely out of control.

Does anyone have an idea of how I can troubleshoot this? I don't even have any compiler warnings.

Doc Block
Apr 15, 2003
Fun Shoe
Maybe it's a symptom of another problem.

How much RAM does your dev system have? Xcode is a RAM hog.

Maybe try a fresh install of Xcode. Run the uninstall script, then delete /Developer and whatever else the various versions of Xcode have left behind.

lord funk
Feb 16, 2004

I have 4 gigs of RAM.

I turned the GDB debugger off - that has stopped the problem. I don't have a debugger, but at least I can work a little more today. Tomorrow I'll reinstall Xcode.

go play outside Skyler
Nov 7, 2005


Help! My objects are getting deallocated when I call removeObjectAtIndex even though the retainCount is far from 0, and numerus references to that object exist in my code

I can't for the life of me understand why the framework is deallocating objects even though they are referenced everywhere else in my code. I can't exactly give you all my code, but here's the idea.

I have a "Partners" NSMutableArray which belongs to my AppDelegate. I create a bunch of "Partner" objects from an xml file I load. I use TBXML to load it remotely, and have a Class Function (read: static) called "createFromTBXML". This function looks something like this:
code:
+ (Partner*)createFromTBXML:(TBXMLElement*)element{
	Partner* partner = [[Partner alloc] retain];
	partner.Name = [TBXML valueOfAttributeNamed:@"name" forElement:element];
	...
        return partner;
}
That partner which is returned is added to the "Partners" NSMutableArray which belongs to the AppDelegate. So far, so good.

These partners are displayed in a list (UITableView) by a PartnerChooserController

Now the tricky part is that people need to be able to add partners to their favorites, so I have a "Favorites" NSMutableArray which also belongs to the AppDelegate. In the Partner detail view, there's a "Add to favorites" button which basically does
code:
[AppDelegate.Favorites addObject:CurrentViewedPartner];
The favorites viewer is basically the same as the PartnerChooserController.

Now what happens is that in the Partner detail view, there's a button "remove from favorites". This button does something like that:
code:
for(int i = 0; i < [AppDelegate.Favorites count]; i++ ){
	if ( ((Partner*)[AppDelegate.Favorites objectAtIndex:i]).Id == CurrentViewedPartner.Id ){
		[Favorites removeObjectAtIndex:i];
		break;
	}
}
As soon as removeObjectAtIndex is called, the partner is deallocated! I don't understand, it's still in the big "Partners" array, it's still being used by the viewer (CurrentViewedPartner) and in other places. In my Partner's dealloc function, I put something like
code:
NSLog(@"deallocated when retainCount is %d",[self retainCount]);
And it shows unbelievable results like "deallocated when retainCount is 8" or even 12! What am I doing wrong here? I've tried adding a bunch of "retain"s here and there, but no luck.

I love Objective-C but the memory management is still a mystery to me, even after reading the Apple documentation about memory management.

Help!

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Do not examine retainCount or pay any attention to it whatsoever. It is the most dangerous form of madness, guaranteed to lead you down the path of destruction.

When an object is being deallocated, what is the point of maintaining retainCount?
Answer: Nothing! by definition, touching a reference after it is deallocated is an invalid operation. Therefore by definition any ivar can return any and all possible values because you are touching memory you promised not to touch. It is no different than saying MyObj *o = (MyObj*)(void*)0x82498384; What is at that memory address? who knows! If you're lucky you'll get an immediate crash.


Second, [[Partner alloc] retain] is not a valid initialized object because you never called init. An alloc'd object is already retained automatically. You should be calling [[Partner alloc] init]. So again, by definition, you can have *any* behavior because you are doing stuff that makes no sense.

Further, a +create method like that should be returning the object autoreleased, so you should be doing [[Partner alloc] init] autorelease]. Then the code that receives the object should retain it if it needs to (placing an object in an array retains it).


You have some serious memory management issues going on and I would suggest reviewing the memory guide, running the Analyze option in Xcode, run the Leaks Instrument, then run with malloc debugging enabled. That should help you track down your memory management issues.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

lord funk posted:

I have 4 gigs of RAM.

I turned the GDB debugger off - that has stopped the problem. I don't have a debugger, but at least I can work a little more today. Tomorrow I'll reinstall Xcode.


I had this stuff happening when I had the Xcode beta installed; it was the system tools being all jacked up. Reinstalling Xcode should fix it, but you may want to go through the command-line uninstall procedure to make sure it completely removes the system tools first.

go play outside Skyler
Nov 7, 2005


Ender.uNF posted:

Do not examine retainCount or pay any attention to it whatsoever. It is the most dangerous form of madness, guaranteed to lead you down the path of destruction.

When an object is being deallocated, what is the point of maintaining retainCount?
Answer: Nothing! by definition, touching a reference after it is deallocated is an invalid operation. Therefore by definition any ivar can return any and all possible values because you are touching memory you promised not to touch. It is no different than saying MyObj *o = (MyObj*)(void*)0x82498384; What is at that memory address? who knows! If you're lucky you'll get an immediate crash.


Second, [[Partner alloc] retain] is not a valid initialized object because you never called init. An alloc'd object is already retained automatically. You should be calling [[Partner alloc] init]. So again, by definition, you can have *any* behavior because you are doing stuff that makes no sense.

Further, a +create method like that should be returning the object autoreleased, so you should be doing [[Partner alloc] init] autorelease]. Then the code that receives the object should retain it if it needs to (placing an object in an array retains it).


You have some serious memory management issues going on and I would suggest reviewing the memory guide, running the Analyze option in Xcode, run the Leaks Instrument, then run with malloc debugging enabled. That should help you track down your memory management issues.

Thank for the help! I reread the documentation and now I understand it better.

HOWEVER, I was not wrong to wonder wtf was happening when the object was being deallocated even though the retainCount was far greater than 1! It turns out, I had this bit of code in the Favoritable class, which is inherited by Partner:
code:
-(void)release{
        [super dealloc];
	Name = nil;
	ShortDescription = nil;
	Icon = nil;
	[super release];
}
What the gently caress was I thinking when I put a dealloc in the release function? Who knows, but now I know it was a stupid as poo poo mistake and I won't ever, ever, ever do this poo poo again.

Spelter
Jul 18, 2007
Are you puissant?

Sir Davey posted:

Thank for the help! I reread the documentation and now I understand it better.

HOWEVER, I was not wrong to wonder wtf was happening when the object was being deallocated even though the retainCount was far greater than 1! It turns out, I had this bit of code in the Favoritable class, which is inherited by Partner:
code:
-(void)release{
        [super dealloc];
	Name = nil;
	ShortDescription = nil;
	Icon = nil;
	[super release];
}
What the gently caress was I thinking when I put a dealloc in the release function? Who knows, but now I know it was a stupid as poo poo mistake and I won't ever, ever, ever do this poo poo again.

It's not just the dealloc that will cause a problem, you shouldn't be doing anything like setting Name, ShortDescription and Icon properties to nil in the release method. In fact, as far as I can see you shouldn't be overriding release at all. If you want to release objects that are properties / member variables of your class, do it in your class' dealloc method, not release.

Doc Block
Apr 15, 2003
Fun Shoe
Why are you overriding release? 99.999% of the time there is no need to do that.

Don't worry about the retain count. Only concern yourself with retaining the things you need to keep around (unless their creator returns them retained) and releasing them when you're done.

If it helps, think of it in terms of ownership. If an object needs another object, and needs it to stay around for a while, then it should probably own that object. It indicates that it owns the other object by retaining it and when it no longer needs that object it relinquishes ownership by calling release on it.

It's ok for an object to have more than one "owner" if you have to, because it just means that both owners need to keep the shared object around.

Just don't call retain on objects whose creator calls retain on them for you, such as with [[Thing alloc] init]. Your object will still own it, and as such will still need to release it.

Zhentar
Sep 28, 2003

Brilliant Master Genius

Spelter posted:

you shouldn't be doing anything like setting Name, ShortDescription and Icon properties to nil

Also you're setting the variables, not the properties, to nil which means you're not actually even releasing them.

ohrwurm
Jun 25, 2003

I am using an older (2007) MBP, not planning to upgrade to Lion yet. I need to reinstall Xcode 4, but the app store only provides the lion-only 4.1 now. Is there a way to get a previous version?

xzzy
Mar 5, 2009

Eggplant posted:

I am using an older (2007) MBP, not planning to upgrade to Lion yet. I need to reinstall Xcode 4, but the app store only provides the lion-only 4.1 now. Is there a way to get a previous version?

You can get dmg files via the Apple developer site.

lord funk
Feb 16, 2004

Not a question, just some idle optimization notes with my current app:

As suggested in a WWDC video, I moved all my graphics calls to a background thread to prevent it from tying up the main thread. It's not a graphics heavy app, but I shaved 30ms off the response time for UITouch events. In the audio world that is huge!

The other big gain was changing a message call from using NSString to a plain old char[]. The original call built an NSString, then it unpacked it into a const char*. That took 200% more work than the actual function of the call. That chopped off about 30-40% of the overall processing.

Edit: just confirmed, the responsiveness is the same whether the graphics are running or not. :dance:

lord funk fucked around with this message at 20:19 on Aug 6, 2011

fankey
Aug 31, 2001

lord funk posted:

As suggested in a WWDC video, I moved all my graphics calls to a background thread to prevent it from tying up the main thread. It's not a graphics heavy app, but I shaved 30ms off the response time for UITouch events. In the audio world that is huge!

Any chance you can point me to which video? I'm also writing an audio / control application and would be interested in checking it out.

lord funk
Feb 16, 2004

WWDC 2011 Session 418 - Best Practices for OpenGL ES on iOS

It doesn't go into too many specifics, but it points out some gotchas that you'll run into with thread safety.

Son of Emhak
Sep 11, 2005

We say there's no parting for us, if our hearts are conveyed to each other.
So I am talking to my landlord, and he wants to make a calendar app, but not just any calendar app or I wouldn't be posting in here. It's a religious calendar, apparently he's in a community that's related to Russian Orthodox but part of an Old Worship Sect, something of that nature. The bottom line is he wants to provide his community with this App for religious observances, like on certain holiday's they aren't allowed to produce income, that sort of daily doctrine. The last offer he got from someone to make this App was $15,000 which sounds a little steep for a calendar. My landlord is going to photocopy the calendar for this year, and create a written outline of specific observances, I'm hoping that is sufficient data to get this off the ground. Please reply to this post or send me a PM if you are interested in taking on this project.

duck monster
Dec 15, 2004

If it where me, I'd quote about $6K for two weeks work. ($2.5K a week or $500 a day or $60hr, plus $1K babysit through the app store process fee)

Alas I'm not free to bid for a few months :(

dizzywhip
Dec 23, 2005

I've been having a lot of trouble with the transition from plain NSViews to Core Animation layers.

I have a custom NSView subclass for the main content area of my application. Think of it as being similar to something like the text editing area of Xcode or any other text editor. Basically, it contains some user-editable content, and the view needs to get taller or shorter based on how the content changes.

I have this working perfectly fine as a standard, non-layer-backed NSView. But I now want to add some Core Animation functionality like animating some components of the content and overlaying layers on top of the content. I've been trying to get this working for quite a while, but I keep running into issues, and I think I'm just not grasping how to properly work with layers in this context.

The main problem I'm having is that in certain situations, when the view resizes itself, the sizing of the layers doesn't seem to stay in sync. So when the view gets taller, for example, the content will be drawn stretched out.

What I'm doing is basically this:

  • Create view's layer and add several sublayers to it.
  • Set delegate of sublayers to the view itself, so that it can draw the layer content.
  • When an action occurs that requires redrawing a layer, call setNeedsDisplay on that layer.
  • Inside the delegate layer drawing method, calculate the content layout, which will resize the enclosing view if needed.
  • Redraw content to the layer.

This is pretty much how I did things before I started doing layers, except that I'd call setNeedsDisplay on the view itself and I'd do the layout and drawing inside drawRect.

The seemingly obvious solution would be to calculate the layout earlier, but I haven't had any luck with that either. I've tried watching WWDC videos, and I've read a lot of documentation, but it never really seems to cover this particular case.

Basically, I'm wondering how you guys would approach this problem. I've been stumped for quite a while. Any advice would be appreciated!

I'm also curious, is there any reason to enable layers in the view's parent views? The view is in a ScrollView which is in a SplitView and so on. Should any of those have layering enabled?

A.S.H. posted:

So I am talking to my landlord, and he wants to make a calendar app, but not just any calendar app or I wouldn't be posting in here. It's a religious calendar, apparently he's in a community that's related to Russian Orthodox but part of an Old Worship Sect, something of that nature. The bottom line is he wants to provide his community with this App for religious observances, like on certain holiday's they aren't allowed to produce income, that sort of daily doctrine. The last offer he got from someone to make this App was $15,000 which sounds a little steep for a calendar. My landlord is going to photocopy the calendar for this year, and create a written outline of specific observances, I'm hoping that is sufficient data to get this off the ground. Please reply to this post or send me a PM if you are interested in taking on this project.

Why not just make a shared calendar in iCal? That can be used in the iPhone calendar app, and unless there's some special functionality he needs, that should work fine.

Small White Dragon
Nov 23, 2007

No relation.
I need to look through some serialized (NSKeyedArchived output) data. Any good tools for this?

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



Small White Dragon posted:

I need to look through some serialized (NSKeyedArchived output) data. Any good tools for this?

From the docs it looks like it's a binary plist. Try writing it to a file with .plist extension and opening it in the Property List Editor.

http://developer.apple.com/library/...WithRootObject:

Small White Dragon
Nov 23, 2007

No relation.

Carthag posted:

From the docs it looks like it's a binary plist. Try writing it to a file with .plist extension and opening it in the Property List Editor.

http://developer.apple.com/library/...WithRootObject:
I've opened it that way, and it's somewhat indecipherable :(

stray
Jun 28, 2005

"It's a jet pack, Michael. What could possibly go wrong?"
I've seen a number of people (not here) who insist that the only proper way to release something is by setting it to nil before releasing it, like so:
code:
- (void)dealloc {
	[foo release], foo = nil;
	[super dealloc];
}
What's the deal with that? Is this a legitimate concern or is this simply being as anal as the people who insist that opening braces should always go on the line after the method declaration? (Because man, gently caress those guys.)

Doc Block
Apr 15, 2003
Fun Shoe
The argument is that if some other thread tries to access the ivar after it's been released but before dealloc is finished, having it be nil'ed out will be "safe".

My opinion is that it's a waste of time. While trying to pass messages to nil might be "safe" in that it won't crash your program, it almost certainly will result in incorrect behavior.

Small White Dragon posted:

I've opened it that way, and it's somewhat indecipherable :(

Binary plists are supposed to be efficient for the archiver. It's not something that's meant to be opened up and edited by hand.

Doc Block fucked around with this message at 04:50 on Aug 8, 2011

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Ok, I know this is a really long post, but this has been driving up the wall and I know the solution is going to make me kick myself either because I've been doing something stupefyingly dumb or the answer is appallingly trivial. Thanks for even reading it; I really want to be able to teach myself this, but with no real frame of reference, I tend to code myself into a corner. I don't mean for anyone to spend tons of time analyzing this, but if anything sticks out as being wrong, I'd appreciate hearing about it. If anything else is wrong, please let me know, I want to do this right.

I'm trying to teach myself GUI programming the Cocoa way (I've previously messed around with C# and Windows Forms–more on that later.) To do this, I decided I would put together a little application which has all the controls on it wired up to do something, in this case generate a little message in a label on the form. In addition, I've been adding some other windows that would normally be found in any application: an about box and a preferences dialog so far. It's the latter that's been giving me trouble.

Essentially, I've been trying to do a little callback in order to get the message label on the main window to display a message when I close the preferences window (Which has a single checkbox–I know I could just have the message appear when the checkbox is clicked, but right now that won't affect this.) Currently, when the Preferences… menu item is clicked, my App Delegate initializes a class of type PreferencesController and stores it in an instance variable of the same type, then shows the window. It also sends a pointer to itself to the instance of the PreferencesController, which stores that pointer in another instance variable. The PreferencesController then requests a BOOL from the App Delegate and sets the checkbox accordingly. Additionally, when the close button on the preferences dialog is clicked, the PreferencesDialog (in theory) sends a message to my App Delegate that preferences are closing. The App Delegate should then get the state of the checkbox, then close the window and release the controller.

Nothing ever happens. The checkbox is unchecked even when the BOOL is set to YES. None of the NSLog statements I put in the preferencesDidChange: method ever print, and the whole app just locks up. Trying to use breakpoints to see what happens is useless because as soon as closePreferences: in PreferencesController finishes, the debugger shows me all the assembly. No issues appear in Xcode and no errors print in the debugger.

I think the reason this isn't working is because I'm using a C# model for this. In that environment, I would just initialize the form and hand it a reference to the controlling class, then have the form tell that class when it was about to close and to get the data it needed, then close the form. I think the differences between C# (and Java, which I'm also more familiar with) and C/Objective-C are messing me up, but with no error messages, I'm at a loss as to what to do.

Here are the headers and implementation files for my App Delegate and the Preferences controller. I've been trying several things to fix various issues, and it's become quite messy as a result.

NotSwingSetAppDelegate.h
code:
#import <Cocoa/Cocoa.h>
#import "MainWindowController.h"
#import "AboutNotSwingSetController.h"
#import "PreferencesController.h"

@class PreferencesController;
@interface NotSwingSetAppDelegate : NSObject <NSApplicationDelegate> {
@private
    NSWindow *window;
    MainWindowController *mainWindow;
    PreferencesController *preferencesWindow;
    
    //Preferences
    BOOL fun;
}
- (IBAction)showAbout:(id)sender;
- (IBAction)showPreferences:(id)sender;
- (void)preferencesDidChange:(BOOL)fun;

@property (assign) IBOutlet NSWindow *window;
@property (retain) MainWindowController *mainWindow;
@property (assign) BOOL fun;

@end
NotSwingSetAppDelegate.m
code:
#import "NotSwingSetAppDelegate.h"

@implementation NotSwingSetAppDelegate
@synthesize window, mainWindow, fun;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    mainWindow = [[MainWindowController alloc] initWithWindowNibName:@"MainWindow"];
    [mainWindow showWindow:self];
    
    //Assign values to preferences
    fun = YES;
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
    return YES;
}

- (IBAction)showAbout:(id)sender {
    NSWindowController *aboutBox = [[AboutNotSwingSetController alloc] initWithWindowNibName:@"AboutNotSwingSet"];
    [aboutBox showWindow:self];
}

- (IBAction)showPreferences:(id)sender {
    preferencesWindow = [[PreferencesController alloc] initWithWindowNibName:@"Preferences"];
    NotSwingSetAppDelegate *delegate = self;
    [preferencesWindow setDelegate:delegate];
    [preferencesWindow showWindow:self];
}

- (void)preferencesDidChange:(BOOL)fun {
    self.fun = fun;
    NSLog(@"Updating Status.");
    [mainWindow updateStatus:[NSString stringWithFormat:@"Fun: %@.", self.fun ? @"Enabled" : @"Disabled"]];
    NSLog(@"Closing window.");
    [preferencesWindow close]; 
    NSLog(@"Releasing window.");
    [preferencesWindow release];
}
@end
PreferencesController.h
code:
#import <Cocoa/Cocoa.h>
#import "NotSwingSetAppDelegate.h"

@class NotSwingSetAppDelegate; //Removes "Unknown type name" error. Wrong/problematic?
@interface PreferencesController : NSWindowController {
    NSButton *funBox;
    NotSwingSetAppDelegate *delegate;
}

- (IBAction)closePreferences:(id)sender;

@property (assign) IBOutlet NSButton *funBox;
@property (assign) NotSwingSetAppDelegate *delegate;
@end
PreferencesController.m
code:
#import "PreferencesController.h"

@implementation PreferencesController
@synthesize funBox, delegate;

- (id)initWithWindowNibName:(NSString *)windowNibName {
    self = [super initWithWindowNibName:(NSString *)windowNibName];
    if (self) {
        // Initialization code here.
    }
    
    return self;
}

- (void)awakeFromNib {
    [funBox setState:[delegate fun]];
}


- (IBAction)closePreferences:(id)sender {
    NSLog(@"Sending Message.");
    [delegate preferencesDidChange:[funBox state]];
}

- (void)dealloc {
    funBox = nil;
    delegate = nil;
    [super dealloc];
}
@end

Zhentar
Sep 28, 2003

Brilliant Master Genius

stray posted:

I've seen a number of people (not here) who insist that the only proper way to release something is by setting it to nil before releasing it, like so:
code:
- (void)dealloc {
	[foo release], foo = nil;
	[super dealloc];
}

The risk addressed by doing that is that if the superclass releases an ivar using the property (e.g. self.bar = nil) and your subclass overrides the setter, and sends a message to foo.

I think it's better to just make a rule of never using properties within dealloc. Outside of dealloc, always set the property to nil.

Doc Block posted:

My opinion is that it's a waste of time. While trying to pass messages to nil might be "safe" in that it won't crash your program, it almost certainly will result in incorrect behavior.

I would say that sending messages to nil gets me the desired behavior somewhere around 95% of the time, and most of the remainder gets explicit nil checks.

Doc Block
Apr 15, 2003
Fun Shoe

carry on then posted:

:words:

I'm just an iOS dev, and still learning Cocoa myself, but I think you should look up key-value observing (KVO) and bindings, which were meant to help alleviate these kind of problems.

Read Cocoa Programming For Mac OS X. While somewhat out of date (2008) it's still a good introduction (and a new edition is supposedly coming in October). The author tries to get the reader to do things The Cocoa Way, which is important if you're coming from another language.

Doc Block fucked around with this message at 06:39 on Aug 8, 2011

NoDamage
Dec 2, 2000

carry on then posted:

Nothing ever happens. The checkbox is unchecked even when the BOOL is set to YES. None of the NSLog statements I put in the preferencesDidChange: method ever print, and the whole app just locks up. Trying to use breakpoints to see what happens is useless because as soon as closePreferences: in PreferencesController finishes, the debugger shows me all the assembly. No issues appear in Xcode and no errors print in the debugger.
I'm guessing that your IBOutlet to your funBox is not hooked up properly in Interface Builder, and possibly your IBAction to your closePreferences method is not hooked up either. Breakpoint in your PreferencesController's awakeFromNib and see if funBox is nil when you're calling setState on it. (This is one adjustment you need to make coming from other languages, calling a method on a nil variable simply does nothing, instead of crashing or showing an error.)

quote:

I think the reason this isn't working is because I'm using a C# model for this. In that environment, I would just initialize the form and hand it a reference to the controlling class, then have the form tell that class when it was about to close and to get the data it needed, then close the form. I think the differences between C# (and Java, which I'm also more familiar with) and C/Objective-C are messing me up, but with no error messages, I'm at a loss as to what to do.
Actually this pattern is quite common in Objective-C and there is a formalized approach for it (protocols and delegates). Suffice to say this is something you'll be doing a lot.

Adbot
ADBOT LOVES YOU

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Thanks both for slogging through that wall of text, I really appreciate the help.

Doc Block posted:

I'm just an iOS dev, and still learning Cocoa myself, but I think you should look up key-value observing (KVO) and bindings, which were meant to help alleviate these kind of problems.

Read Cocoa Programming For Mac OS X. While somewhat out of date (2008) it's still a good introduction (and a new edition is supposedly coming in October). The author tries to get the reader to do things The Cocoa Way, which is important if you're coming from another language.

Hmm, I've been looking for a decent textbook, and that just might be it. Good suggestion.

NoDamage posted:

Breakpoint in your PreferencesController's awakeFromNib and see if funBox is nil when you're calling setState on it. (This is one adjustment you need to make coming from other languages, calling a method on a nil variable simply does nothing, instead of crashing or showing an error.)
It shows funBox as an NSButton pointer, so that looks alright. It also says delegate is a NotSwingSetAppDelegate pointer, but the address is just 0x0. Could that have something to do with it? Am I not getting a proper pointer to the controller?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply