implementing Singleton for xib, with initWithCoder and delegate - objective-c

so my problem is this:
I'm trying to have a singleton for a custom view xib. When I fire a notification it's not getting caught by the observer, because apparently my combobox has a different 'self' than '_sharedInstance'.
here is the code - initWithCoder:
-(id)initWithCoder:(NSCoder *)coder{
if (_sharedInstance){
self = _sharedInstance;
return self;
}else{
_sharedInstance = [super initWithCoder:coder];
return _sharedInstance;
}
}
awakeFromNib: (because in initWithCoder: _sharedInstance.cmbBox is nil)
-(void)awakeFromNib{
_sharedInstance.cmbBox.delegate = _sharedInstance;
}
The delegate that should catch the combobox selection:
// NSComboBoxDelegate:
-(void)comboBoxSelectionDidChange:(NSNotification *)notification{
if (notification.object == _sharedInstance.cmbBox){
NSLog(#"Do Something!");
[[NSNotificationCenter defaultCenter] postNotificationName:#"DoSomething" object:_sharedInstance userInfo:nil];
}
}
The problem is notification.object != _sharedInstance.cmbBox, so it never enters the if statement...
Did I do something stupid? :)

Related

How to access dataSource outlet class from UITableView?

i have one MYViewController which contains MYTableView, with settings:
1) dataSource outlet is delegated to MYDataSource
2) delegate of MYTableView is set to MYTableView
I have the code in delegate class
//MYTableView (delegate is set in storyboard)
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
//code here
[(MYDataSource *) self.dataSource loadMoreWithSuccess:^(){
[self reloadData];
}];
}
but, the dataSource loadMoreWithSuccess cant be accessed, how to call it?
UPD
So, after some debugging, i've ended up with following:
//MYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self initTable];
}
-(void) initTable{
NSLog(#"dataSource: %s", class_getName([_table.dataSource class]));
// dataSource: MYDataSource
NSLog(#"delegate: %s", class_getName([_table.delegate class]));
// delegate: MYTableView
}
but in MYTableView when i do the following, i get
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
NSLog(#"dataSource: %s", class_getName([self.dataSource class]));
// dataSource: nil
NSLog(#"delegate: %s", class_getName([self.delegate class]));
// delegate: nil
}
Maybe i didn't notice something important in the Apple Developer Guide?

__NSStackBlock__ isEqualToString: issue

I am experimenting with this code.
In one of viewController's I am using next snippet:
- (BOOL)textView:(UITextView *)textView1 shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
return NO;
}
return YES;
}
I found in web to dismissing the keyboard by pressing returnButton. It works well when I am calling it from this viewController. In root KLNoteViewController I am adding notification in handle state changes-method:
- (void) setState:(KLControllerCardState)state animated:(BOOL) animated
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"refresh" object:self];
if (animated)
{
[UIView animateWithDuration:self.noteViewController.cardAnimationDuration animations:^{
[self setState:state animated:NO];
}];
return;
}
//Full Screen State
if (state == KLControllerCardStateFullScreen)
{
[self expandCardToFullSize: animated];
[self setYCoordinate: 0];
}
//Default State
else if (state == KLControllerCardStateDefault)
{
[self shrinkCardToScaledSize: animated];
[self setYCoordinate: originY];
}
//Hidden State - Bottom
else if (state == KLControllerCardStateHiddenBottom)
{
//Move it off screen and far enough down that the shadow does not appear on screen
[self setYCoordinate: self.noteViewController.view.frame.size.height + abs(self.noteViewController.cardShadowOffset.height)*3];
}
//Hidden State - Top
else if (state == KLControllerCardStateHiddenTop)
{
[self setYCoordinate: 0];
}
//Notify the delegate of the state change (even if state changed to self)
KLControllerCardState lastState = self.state;
//Update to the new state
[self setState:state];
//Notify the delegate
if ([self.delegate respondsToSelector:#selector(controllerCard:didChangeToDisplayState:fromDisplayState:)]) {
[self.delegate controllerCard:self
didChangeToDisplayState:state fromDisplayState: lastState];
}
}
and add adding observer:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dismissKeyboard) name:#"refresh" object:nil];
in every viewControllers -viewDidLoad. So when this observer is used with UITextField everything works fine, in viewController when I am using UIText View I have crash with log:
[NSStackBlock isEqualToString:]: unrecognized selector sent to
instance 0xbfffd228
I searched in web but found only two links with explanation of what is the NSStackBlock is and they are not informative well for me to solve the problem. Can somebody explain what it can be?

NSView mouseExited

I have an NSView and basically, even when my mouse doesn't leave the defined frame, just moves within it, mouseExited function is called. Is this how is it suppose to be or am I doing something wrong? There are several subviews of this NSView and it's custom and here's the code for it:
- (id)initWithDelegate:(id)del {
if (self = [super init]) {
[del retain];
delegate = del;
}
return self;
}
- (void)dealloc {
[delegate release];
[super dealloc];
}
- (void)viewDidMoveToWindow {
[self addTrackingRect:[self bounds]
owner:self
userData:nil
assumeInside:NO];
}
- (void)mouseEntered:(NSEvent *)theEvent {
[delegate mouseEntered];
}
- (void)mouseExited:(NSEvent *)theEvent {
NSLog(#"mouse exited");
[delegate mouseExited];
}
- (void)mouseDown:(NSEvent *)theEvent {
[delegate mouseDown];
}
- (NSView *)hitTest:(NSPoint)aPoint {
return self;
}
Thanks.
I figuered it out. After adding a tracking area, i was changing the frame of my view so I needed to recalculate the tracking area. Found this method that will automatically be called whenever tracking area needs to be updated:
- (void)updateTrackingAreas {
Just simply recalculate your tracking area here.

Objective C Class Method to control all existing instances?

Is it possible to use the class methods of some NSObject I've made to controls all existing instances?
I want a delegate class to be able to send messages to the Object's class methods which can then react appropriately with everything out there.
Sure. Just have all the objects register for notifications when they're created. For example:
- (id)init {
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(announceYourself:)
name:#"MYCLASS_ANNOUNCE"
object:nil];
return self;
}
+ (void)identifyInstances {
[[NSNotificationCenter defaultCenter] postNotificationName:#"MYCLASS_ANNOUNCE" object:self];
}
- (void)announceYourself:(id)notification {
NSLog(#"Instance %p reporting in!", self);
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self]; // VERY IMPORTANT -- IT WILL CRASH WITHOUT THIS
[super dealloc];
}
Not without using some collection of the objects. The simplest way to do it would be to store the objects in an array and send them all a message when you want something to happen. Specifically:
static NSMutableArray *allObjects = nil;
+ (void) initialize {
if (!allObjects) {
allObjects = [NSMutableArray new];
}
}
- (id) init {
if (self = [super init]) {
//Each object gets held in an array
[allObjects addObject:self];
}
return self;
}
+ (void) doSomethingToEveryObject {
[allObjects makeObjectsPerformSelector:#selector(doSomethingToThisObject)];
}
- (void) doSomethingToThisObject {
NSLog(#"Did something to %#",self];
}
- (void) release {
[super release];
//When the retain count reaches 1, then all external references have disappeared,
//and the only remaining reference is in the objects array.
if (self.retainCount == 1) {
[allObjects removeObject:self];
}
}

Loading presentModalViewController in ViewDidAppear causes EXC_BAD_ACCESS

In the Follwoing ViewControllerClass I get EXC_BAD_ACCESS when trying to call presentModalViewController in ViewDidAppear method.
#import "SounderViewController.h"
#import "ASIFormDataRequest.h"
#import "ASIHTTPRequest.h"
#import "JSON.h"
#import "InfoViewController.h"
#implementation SounderViewController
#synthesize ipod;
#synthesize ivc;
#synthesize title_lb, artist_lb, check;
-(IBAction)showCurrentSongInfo{
MPMediaItem * song = [ipod nowPlayingItem];
NSString * title = [song valueForProperty:MPMediaItemPropertyTitle];
NSString * artist = [song valueForProperty:MPMediaItemPropertyArtist];
title_lb.text = title;
artist_lb.text = artist;
}
-(void)playbackStateChanged: (NSNotification*) notification{
[self showCurrentSongInfo];
NSLog(#"Playback state: %#",[notification name]);
if (ipod.playbackState != MPMusicPlaybackStatePlaying) {
NSLog(#"Is not playing");
[self presentModalViewController:self.ivc animated:YES];
}else if (ipod.playbackState == MPMusicPlaybackStatePlaying) {
NSLog(#"Is playing");
[self dismissModalViewControllerAnimated:YES];
}
}
-(void)nowPlayingItemChanged: (NSNotification*) notification{
[self showCurrentSongInfo];
NSLog(#"Playing item changed: %#",[notification name]);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.ivc = [[InfoViewController alloc] initWithNibName:#"InfoViewController" bundle:nil];
self.ipod = [MPMusicPlayerController iPodMusicPlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector (playbackStateChanged:)
name:#"MPMusicPlayerControllerPlaybackStateDidChangeNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector (nowPlayingItemChanged:)
name:#"MPMusicPlayerControllerNowPlayingItemDidChangeNotification"
object:nil];
[[MPMusicPlayerController iPodMusicPlayer] beginGeneratingPlaybackNotifications];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if (ipod.playbackState != MPMusicPlaybackStatePlaying) {
[self presentModalViewController:self.ivc animated:YES];
}else{
[self showCurrentSongInfo];
}
}
-(IBAction)showInfoView{
[self presentModalViewController:self.ivc animated:YES];
}
#pragma mark View Methods
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Method call
[self presentModalViewController:self.ivc animated:YES];
in ViewDidAppear causes EXC_BAD_ACCESS.
I have tried debuging it with NSZombieEnabled but got only a stack call to main.
The thing that gets me crazy is that if the same code is run from method playbackStateChanged it works fine.
If any of you can help I wan't get bold as quick. Thanks.
I finally made it to work! But I think it's just quick fix.
So I found out that to make my ivc to show up I need to delay the call to presentModalViewController
[self performSelector:#selector(showWaitingMessageView:) withObject:self.ivc afterDelay:1];
That's it. It works.
I don't know why this helped, so if one of you gurus knows more about it please enlighten me.