Objective C - How to access NSNotification inner objects? - iphone

I want to access a inner object from a notification. I need to get the key AVSystemController_AudioVolumeChangeReasonNotificationParameter.
If I call [sender object] I get this output. But if I call
[[sender object] userInfo]
I only get "unrecognized selector sent to instance". Why is that?
NSLog(#"%#", [sender object]) output:
NSConcreteNotification 0x157a30 {name = AVSystemController_SystemVolumeDidChangeNotification; object = AVSystemController: 0x1616c0; userInfo = {
"AVSystemController_AudioCategoryNotificationParameter" = "Audio/Video";
"AVSystemController_AudioVolumeChangeReasonNotificationParameter" = ExplicitVolumeChange;
"AVSystemController_AudioVolumeNotificationParameter" = 1;
}}
If it is not possible to access userInfo, can I get the output of NSLog to do a string search?

Your output from NSLog actually looks like the output of
NSLog(#"%#", sender);
Are you sure you were calling [sender object]?
object is often the Object that posted the notification. In your case most likely an object with class AVSystemController
The userinfo can be accessed with
[sender userInfo]
So please try
NSLog(#"%#", [sender userInfo]);
BTW: If you try to map the function of the volume-buttons to some other function (for example "Take Photo"-Action) your app won't be approved. Just in case.

Related

How to pass NSError to method

I have a method which take the parameter
(void(^)(NSError*))errorCall;
I need to pass errorCall value
-(void)message{
example = [[Example alloc]init]
[example opertationError:void(^)(NSError*))errorCall ];
}
for the below line
[example opertationError:void(^)(NSError*))errorCall];
i need to pass some custom error call which in type of void(^)(NSError*))errorCall
Please any one let me know how to pass this kind of error value to the method.
#All
Thanks in advance
You can do like this:
void(^aBlock)(NSError *) = ^(NSError *error) {
...
};
[self errorValue:aBlock];

OCUnit Test Case Issue

I am working OCUnit Test case
- (NSDictionary*)Event:(EventBase*)event
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
I found this method to write the test case
In my Test Case Class i pass the event value valid,invalid and nil for the above method
-(void)testEventNil{
NSDictionary *t_Dict;
EventClass *t_EventClass = [[EventClass alloc]init];
t_Dict = [t_EventClass Event:nil];
STAssertNil (t_Dict, #"Return nil");
}
-(void)testEventNil{
NSDictionary *t_Dict;
NSMutableDictionary *invalid;
[invalid setObject:#"1324" forKey #"Number"];
EventClass *t_EventClass = [[EventClass alloc]init];
t_Dict = [t_EventClass Event:];
STAssertNil (t_Dict, #"Return nil");
}
-(void)testEventvalid{
NSDictionary *t_Dict;
NSMutableDictionary *invalid;
[invalid setObject:#"WorkNameEvent" forKey #"EventNameKey"];
EventClass *t_EventClass = [[EventClass alloc]init];
t_Dict = [t_EventClass Event:];
STAssertNotNil (t_Dict, #"Return nil");
}
Its gives me error unrecognized selector sent to instance
Can any one advice me for fixing the issue
#All
Thanks in advance
Your code has multiple errors. I can't make sense of it.
You are trying to test a method that is designed to throw an error. Maybe it is intended to be overriden? The only possible test as it is now is
EventClass *event = [EventClass new];
STAssertThrows([t_EventClass Event:nil],#"Should throw an error.");
When you write: t_Dict = [t_EventClass Event:]; you are not passing any parameter to the Event: method.
This doesn't work either:
NSMutableDictionary *invalid;
[invalid setObject:#"WorkNameEvent" forKey #"EventNameKey"];
because you didn't initialize the dictionary. That is,
NSMutableDictionary *invalid = [NSMutableDictionary new];
The convention in Objective-C is to name methods and variables using camel case, in this case event: instead Event:, and dic instead t_Dic.

NSMutableArray lastObject not working in UITableView iPhone?

I want to get the last object from an NSMutableArray. When I use the code below to get the last object from the NSMutableArray it is not finding it:
if ([mutableArray lastObject])
{
NSLog(#"Last Object");
}
else
{
NSLog(#"Not a Last Object");
}
When ever I call this code the if statement is only calling for every objects from an array. Can anyone please help me to solve this?
[mutableArray lastObject] returns an id typed object which is the last object of your array. it is not a test.
To see it you should write something like :
id myLastObject = [mutableArray lastObject];
NSLog(#"my last object is : %#",myLastObject);
edit :
What do you mean by check last object ?
checking equality with the isEqual method checks if both objects are same objects, meaning only one object but you might wanna check if two objects have same properties, thus checking if properties have same values.
if ([someObject isEqual:[mutableArray lastObject]]) {
NSLog(#"Last Object");
}

Struggling to get the Dictionary passed with NSNotification

I received the notification so I handle it like so
-(void) dateSelected:(NSNotification *) notification
{
NSLog(#"Value: %#", [[notification userInfo] valueForKey:#"date"] );
NSMutableDictionary * dateDict = [[NSDictionary alloc] initWithDictionary:[notification userInfo]];
NSLog(#"The Date Dict: %#", dateDict );
}
The logs I get are
2012-07-20 11:32: TestApp[10701:40b] Value: (null)
2012-07-20 11:32: TestApp[10428:40b] The Date Dict: {
}
If I NSLog out the notification itself it looks valid:
2012-07-20 11:33: TestApp[10457:40b] Notification: NSConcreteNotification 0x16629460 {name = date_selected_; object = {
date = 20120705;
}}
I've done this before and its worked.
I'm sure its simple, but today I cannot see the issue.
Any help would be appreciated.
Thanks,
-Code
It's pretty simple, look at your log output ... There's no userInfo set in your notification. There's just name and object. Compare your output with this one ...
NSNotification *notification = [NSNotification notificationWithName:#"NAME"
object:self
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:#"obj", #"key", nil]];
NSLog( #"NOT: %#", notification );
...
NOT: NSConcreteNotification 0x73586f0 {name = NAME;
object = <CMAppDelegate: 0x884a4e0>; userInfo = {
key = obj;
}}
... see the difference? There's name, object, but also userInfo in log output.
So the answer is - your notification does not contain userInfo dictionary. Look at code which fires this notification.

EXC_BAD_ACCESS iOS error

I know, I know. I've Google and searched here but can't figure out what's going on.
Anyway, i'm getting this error when using the following code, i'm sure it's something small. I know it's to do with memory management and down to how i'm handling my object in the main method.
Here's my main code:
Person *p1 = [[Person alloc] init];
[p1 initWithFirstname:#"John" lastname:#"Doe" andAge:23];
outputText.text = [p1 getDetails]; // App crashes inside getDetails
Then in the person class here's the two relevant methods:
-(Person *)initWithFirstname:(NSString *)_firstname lastname:(NSString *)_lastname andAge:
(int)_age {
self = [super init];
if(self) {
self.firstname = _firstname;
self.lastname = _lastname;
self.age = _age;
}
return self;
}
-(NSString *)getDetails {
return [NSString stringWithFormat:#"%# %#, %#", firstname, lastname, age];
}
Judging by your init method, age is an int which means the format specifier is wrong. Try this:
-(NSString *)getDetails
{
return [NSString stringWithFormat:#"%# %#, %d", firstname, lastname, age];
// ^^ format specifier for an int
}
You've written an initialization method, then called init twice. Just try:
Person *p1 = [[Person alloc] initWithFirstname:#"John" lastname:#"Doe" andAge:23];
outputText.text = [p1 getDetails];
You're first calling the default init of your newly allocated object. That init returns a pointer to your object which you store in p1. Then you call initWithFirstname:lastname:andAge: on p1, which is wrong as you've already called another initializer first. You're only supposed to run one initializer.
You need to do:
Person *p1 = [[Person alloc] initWithFirstname:#"John" lastname:#"Doe" andAge:23];
But your crash stems from the fact that you pass the number 23 to the format specifier %#. You need to use %d for the age instead. Also, you should retain the first and last name (and release them in your dealloc) to avoid any crashes later on when using non-const strings.
What happens is that because of %#, the NSLog tries to treat the 23 as a pointer to an object and wants to call the description method of the supposed object. But 23 is an invalid/unused address, and trying to access the memory at that "address" is what makes your app crash.