Objective-C: Getting notification names from all NSDistributedNotificationCenter notifications? - objective-c

I'm sure I had a tool that could log all system wide notifications but, not being able to find it, I'm writing my own.
So the documentation says I set up the observer by calling:
- (void)addObserver:(id)notificationObserver
selector:(SEL)notificationSelector
name:(NSString *)notificationName
object:(NSString *)notificationSender
…but I don't want to listen to any one notification or object in particular so I set those values to nil. So far so good, I know when notifications are being broadcast.
But how do I get the names of the unknown notification and senders once they've been received? Is it possible?

From the docs:
The method specified by notificationSelector must have one and only one argument (an instance of NSNotification).
Therefore:
-(void)observerMethod:(NSNotification*)notification
{
NSLog( #"%#", notification);
}
The name is a property of the passed notification. The sender is usually the property object. (It is not really the sender, but if somebody else is the sender, the object will be more interesting.) You can retrieve additional information from the userInfo property.
BTW, take care: The selector in this example is observerMethod:, not observerMethod (colon included).

Related

How do I prevent exception" An instance was deallocated while key value observers were still registered with it." when I don't know the observer?

I'm getting the following KVO NSInternalInconsistencyException
> An instance 0x61800005a610 of class portController was deallocated
> while key value observers were still registered with it. Current
> observation info: "<NSKeyValueObservationInfo 0x610000055f90> (
> <NSKeyValueObservance 0x6100000c25a0: Observer: 0x6180000c7460, Key
> path: serialPortManager.availablePorts, Options: <New: NO, Old: NO,
> Prior: NO> Context: 0x0, Property: 0x608000080d20> ")
serialPortManager, by the way, is the singleton [ORSSerialPortManager sharedSerialPortManager]. The obvious answer, of course, is to use
[portController removeObserver:observer forKeyPath:#"serialPortManager.availablePorts"];
Problem is, I don't know who Observer: 0x6180000c7460 is. The key path is set in IB (storyboard) where the content of an NSPopUpButton is bound to a viewController, keyPath self. portController.serialPortManager.availablePorts. portController has a weak reference to serialPortManager.
I have tried looking up the address of the observer in the dSYM via dwarfdump -a in the terminal, but no luck. Is this a new thing? I don't remember having these problems with bindings in the past.
EDIT:
I did not make it explicit, but the address of the NSPopUpButton is not that of the observer.
EDIT 2:
I have implemented #Martin Brugger's solution to Objective C:Object Deallocated while key value observers were still registered with it which is to add symbolic breakpoint for NSKVODeallocateBreak. Unfortunately, the breakpoint is never reached, but error still shows up in the console. I'm starting to think I should file a bug report.
Put the remove observer call into the dealloc method of your class.

The correct way to design data loading and object creation

I'm working on an app for iphone where I load a JSON from a php server, parse it with a library and create an object with this data. My code works fine but the way I do it seems wrong to me:
A viewController shows to the user a loading view. Meanwhile the ViewController makes the get request and receive the data.
The VC parse the response and get a dictionary
The dictionary is send to a "creator class" who returns a object created from the dictionary
I do two times this operation but I think it's a bad design:
Should a View Controller do a http request? Don't shoud be a "objectLoader"? The main method of creation class makes a big bunch of if/else spaghettis, like:
for(NSString key in dictionary){
if(key isEqualToString "a key"){
perform action
}
else if(key isEqualToString "an other key"){
perform action
}
....
}
Any idea to solve that? I was thinking about make a dictionary of keys/selectors to solve it and do something like:
for(NSString key in dictionary){
[self performSelector:[selectors getObjectForKey:key]]
}
But I don't know if I can reference a selector in a dictionary...
Finally the other option that comes to me is send the parsed dictionary to the object with a class method like: [ClassName createObjectWithDictionary:parsedDictionary]. That's a good way to do it?
I know the question is a little ambiguous but I'm a little lost in what Design patterns I should apply and who is responsible of what in this story
the best way is to use MVC pattern and have model with data that has methods to push and remove some data inside it and a list of delegates (derived from UIViewController) which are notified in case of changed model data.
Controller (not UIViewController) is something that initiates fetching data from server and handles results.
And all of UIViewControllers handles data changes and user interaction.
For now, write some RequestController (singletone or not, doesn't matter) that handles request routines and stores all necessary data to trigger events in controller.
You can use blocks or NSNotificationCenter to handle request's completion.
After getting necessary data through RequestController from request, your Controller can create necessary parsers and push parsed data into model.
Personally, I would NOT let the ViewController do the HTTP request. I always write service classes in my apps, that do the low level stuff and inform the caller (e.g. a view controller) via delegation on any received result.
So the control flow in that case is:
-> ViewController locks screen with loading message
-> calls service with itself as delegate - the service does the work and receives the answer -> the answer is processed and the result passed to the delegate
-> the ViewController takes the response, removes the loading message and does whatever is necessary with the response.
Concerning your second question: yes, it is possible to dynamically chose a selector out of a dictionary - e.g. by storing the selector's name in the dictionary and then use
SEL selector = selectorFromString(#"doWork");
to create the right selector to call.

Objective-c, passing NSURLConnection result to a View Controller

Long time reader, first time poster here.
I'm creating a test app that creates a NSURLConnection and then displays the result on an UILabel.
I am presently using a Notification Center observer, which fires a notification from within connectionDidFinishLoading to wait for the connection to complete successfully, before I look for the result.
However, what I am struggling to conceptualize is where to store the response data so that I can access it from my View Controller and post the result to the UILabel. (Or from anywhere other than an instance of my Connection Class, for that matter.)
I don't want to post directly to the UILabel from connectionDidFinishLoading. I need a way to decide what I will do with the response later - so my Connection Class stays generalized.
I need a better way to save the response data somewhere, where I can reference it after the instance of the Connection Class has terminated.
Ideally, it should be somewhere that I can have multiple instances of the Connection Class open, and access each response in turn as I need them. This eliminates the potential to just create a variable in my View Controller or somewhere else more global and dump the response to it.
Any ideas on what design patterns could/should be used here would be greatly appreciated!
My suggestions for you to start with are :
Make a singleton class. I will have a property NSDictionary * info or NSArray *infoList; You will have acces to the same data from wherever the app. Update the property, post the notification, access the property from the viewController.
Store the info into a plist/file. Serialize the information, or save plain stream. Whatever you like.Thus after you finish writing to the file, post the notification, read from the file from anyplace within the app.
In both cases if you want multiple connections i suggest going for the factory design Pattern.

Dropbox API in iOS: How to use DBRestClient?

I'm trying to follow the instructions on the Dropbox developer's site, but I can't figure out how to properly add a DBRestClient object. Right now in my .h file after #end I have:
DBRestClient *restClient;
And in my .m file I have:
- (DBRestClient *)restClient {
if (!restClient) {
restClient =
[[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
}
return restClient;
}
This is what the Dropbox page tells me to do, I think; however this results in my app crashing (I think because it tries to release restClient when it shouldn't). I've also tried listing restClient as a nonatomic property but then the uploading, etc methods don't seem to work. (The upload method IS working right now, the app just crashes once it's finished uploading...) Help?
Rupesh, the detailed canonical answer based on bee's comment on Apr 20 is that self was getting deallocated.
this means there must have been code that did the following in order.
a variable created by calling the restClient function that returns an object of type (DBRestClient*)
that variable sets it's component (#property? probably) delegate to self in that function (seen in the
question above)
later, the object self was pointing to was deallocated, meaning delegate was not pointing to anything.
later still, there must have been code that was attempting to dereference delegate for some purpose.
do remember that sending messages to nil objc objects only effectively results in nothing happening or a zero assignment if the message being sent is a function. thus a crash must have been due to some other kind of dereference.

Objective-C respondsToSelector

From what I have learned so far: In Objective-C you can send any message to any object. If the object does implement the right method it will be executed otherwise nothing will happen. This is because before the message is sent Objective-C will perform respondsToSelector.
I hope I am right so far.
I did a little program for testing where an action is invoked every time a slider is moved. Also for testing I set the sender to NSButton but in fact it is an NSSlider. Now I asked the object if it will respond to setAlternateTitle. While a NSButton will do and NSSlider will not. If I run the code and do respondsToSelector myself it will tell me the object will not respond to that selector. If I test something else like intValue, it will respond. So my code is fine so far.
- (IBAction)sliderDidMove:(id)sender
{
NSButton *slider = sender;
BOOL responds =
[slider respondsToSelector:#selector(setAlternateTitle)];
if(responds == YES)
{
NSLog(#"YES");
}
else
{
NSLog(#"NO");
}
[slider setAlternateTitle:#"Hello World"];
}
But when I actually send the setAlternateTitle message the program will crash and I am not exactly sure why. Shouldn't it do a respondsToSelector before sending the message?
First of all, the name of a method (its selector) includes all subparts and colon characters, as mvds said.
Second of all, the method -respondsToSelector: is not called by the runtime, it's usually called by the user (yourself or APIs that want to know if a delegate, for example, responds to an optional method of the protocol).
When you send a message to an object, the runtime will look for the implementation of the method in the class of the object (through the object's isa pointer). It's equivalent to sending -respondsToSelector: although the message itself is not dispatched. If the implementation of the method is found in the class or in its superclasses, it's called with all the arguments you passed in.
If not, then the runtime gives the message a second chance to be executed. It will start by sending the message + (BOOL)resolveInstanceMethod:(SEL)name to the class of the object: this method allows you to add the method at runtime to the class: if this message returns YES, it means it can redispatch the message.
If not it gives the message a third chance to be executed, it sends - (id)forwardingTargetForSelector:(SEL)aSelector with the selector, this method can return another object that may be able to respond to the selector on behalf of the actual receiver, if the returned object can respond, the method is executed and the value is returned as if it was returned by the original message. (Note: This is available beginning with OS X 10.6 or iOS 4.)
If the returned object is nil or self (to avoid infinite loops), the runtime gives the message a fourth chance to execute the method… It sends the message - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector to get a method signature in order to build an invocation. If one is provided then an invocation is sent through the message - (void)forwardInvocation:(NSInvocation *)anInvocation. In this method you can parse the invocation and build other messages to send to other targets in any ways you want, and then you can set the return value of the invocation… That value will act as the return value of the original message.
Finally, if no method signature is returned by the object, then the runtime sends the message - (void)doesNotRecognizeSelector:(SEL)aSelector to your object, the implementation of this method in NSObject class throws an exception.
For one thing, the selector is not only the "name" of the message, but also what follows, i.e. the arguments, and their names.
So the correct selector for some -(void)setAlternateTitle:(NSString*)str would be
#selector(setAlternateTitle:)
with the :
As for your problem: If a class respondsToSelector() and you perform that selector, you shouldn't get a crash on sending an unknown selector. What kind of crash log do you see in the debugging window?
(ps. why not include the [slider setAlternateTitle:...] in the if ( responds ) { ... } conditional block?)
"This is because before the message is
sent Objective-C will perform
respondsToSelector."
I guess this is not correct. If the object does not respond to selector, it will crash at runtime. There is no automatic checking by the system. If there was a check by the run time system then we should never get "unrecognized selector sent to instance" exception.
Please make me correct if I am wrong.
EDIT: This is not a straight forward crash, but the default result is the process will be terminated. The whole sequence is already explained in comment and other answer, so I am not going to write that again.
There is an +instancesRespondToSelector: method. As the name suggests, it tells you whether the instances of the class implement that method.