NSlog showing odd output - objective-c

I have a NSlog that is giving odd output in the debugger. How do I get it to show the proper value?
NSError *error = nil;
NSArray *data;
[self setStatus:#"Syncing data..."];
self.userInfo = [self.cloud Authenticate:[self serialNumber]];
if ( self.deviceInfo )
{
data = [self.device GetData:&error];
if ( !data )
{
[self displayErrorMessage:error];
data = [NSMutableArray array];
}
//data received from device: Log point
NSLog(#"data received from device: %#",data);
Debuger output
"<DataPoint: 0x1001f81b0>",
"<DataPoint: 0x10012f5f0>",
"<DataPoint: 0x1001f7780>",
"<DataPoint: 0x1001f8780>",

This is the default string returned by NSObject's description method, which just prints the pointer value. If you want to see the proper data printed, override description in your DataPoint class:
- (NSString*) description
{
// Example:
return [NSString stringWithFormat: #"ivar1=%# , ivar2=%#",ivar1, ivar2];
}

As you stored an object of DataPoint in the array, correct output is shown.
If you want to see full value for each of them, then you need to use
for(DataPoint *dp in data){
NSLog(#"%#",dp.property);//property should be your property name of DataPoint class.
}

+1 for #Ramy's good suggestion to override description, I suggest extending, rather than replacing, like this:
- (NSString *)description {
return [NSString stringWithFormat: #"%#: ivar1=%#, ivar2=%#",
[super description], self.ivar1, self.ivar2];
}
The inherited behavior that answers the class and the %p pointer is very useful, too.

Related

How to parse and take only this string value

I wanted to get only array string value app. As example(SLGoogleAuth ,HalfTunes,TheBackgrounder,Calculiator) . But don't know how to do?
It's a code.
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
SEL selector=NSSelectorFromString(#"defaultWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
SEL selectorALL = NSSelectorFromString(#"allApplications");
NSLog(#"apps: %#", [workspace performSelector:selectorALL]);
}
It's output:
Thanks in advance
You do not want to parse that. NSLog prints out a description of an object. You want to access that value directly.
[LSApplicationWorkspace allApplications];
returns NSArray of LSApplicationProxy. LSApplicationProxy class has a ivar _bundleURL that contains information that you need. You need runtime functions to access it. Working example below:
// #import <objc/runtime.h>
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
SEL selector=NSSelectorFromString(#"defaultWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
SEL selectorALL = NSSelectorFromString(#"allApplications");
NSArray* appProxies = [workspace performSelector:selectorALL];
Ivar bundleUrlIvar = class_getInstanceVariable([appProxies.firstObject class], "_bundleURL");
NSMutableString* result = [NSMutableString string];
for (id appProxy in appProxies)
{
NSURL* url = object_getIvar(appProxy, bundleUrlIvar);
// at this point you have the information and you can do whatever you want with it
// I will make it a list as you asked
if (url)
{
[result appendFormat:#",%#", [url lastPathComponent]];
}
}
if (result.length > 0)
{
// remove comma from beginning of the list
[result deleteCharactersInRange:NSMakeRange(0, 1)];
}
NSLog(#"apps: %#", result);
Note that this will be rejected by AppStore as you are using private apis. So use at your own discretion.

Building 3 methods in Objective C

I'm having trouble with a school problem in Objective C. I need to build 3 methods. The first method tells you if someone is in a line. If nobody is in the line it tells you nobody is in the line otherwise it tells you who is in the line and it lists the names on a new line.
The second method adds names to the line.
The third method removes a name from the line and tells you who was removed.
First method:
-(NSString*)stringWithDeliLine:(NSArray*) deliLine{
NSString *empty = #"The line is currently empty.";
//Some kind of formatted string
if(deliLine == nil || [deliLine count] == 0)
{
empty;
}
else
{
//formatted string
}
//not sure how to return either empty or formatted string
}
Second Method:
-(void)addName:toDeliLine:(NSString*)name:(NSMutableArray*)deliLine{
[deliLine addObject:name];
}
The third method I was going to use removeObject but the instructions said not to use it so I have no idea where to start.I have the signature I think.
-(NSString*)serveNextCustomerInDeliLine:(NSMutableArray*)deliLine{
return nil;
}
For the first method I'm not sure why my literal string won't work in the if statement. I thought I was saying look at the array if nothing is in the array then it's the first object and show the string literal. else show some kinda of formatted string. I've tried all kinds of strings but none seem to be working so that's why I have the comment formatted string. If someone could give me a hint that would be great. I don't need the answer just a clue on what to think about. This is long post sorry.
A possible implementation can be the following. Please note that I have not testes edge cases and I wrote the code without Xcode support
#import <Foundation/Foundation.h>
#interface Line : NSObject
- (NSString*)printLine;
- (void)addCustomer:(NSString*)customer;
- (NSString*)removeCustomer:(NSString*)customer;
#end
#import "Line.h"
#interface Line ()
#property (nonatomic, strong, readwrite) NSMutableArray<NSString*> *customers;
#end
#implementation Line
- (instancetype)init {
self = [super init];
if (self) {
_customers = [NSMutableArray array];
}
return self;
}
- (NSString*)printLine {
NSUInteger count = self.customers.count;
if(count == 0) {
return #"Empty";
}
NSMutableString *descr = [NSMutableString string];
for (NSString *customer in self.customers) {
[descr appendString:[NSString stringWithFormat:#"%# ", customer]];
}
return [descr copy];
}
- (void)addCustomer:(NSString*)customer {
[self.customers addObject:customer];
}
- (NSString*)removeCustomer:(NSString*)customer {
NSUInteger index = [self.customers indexOfObject:customer];
if(index == NSNotFound) {
return [NSString stringWithFormat:#"%# not removed", customer];
}
NSString *removedCustomer = [self.customers objectAtIndex:index];
[self.customers removeObjectAtIndex:index];
return removedCustomer;
}
#end
Usage:
Line *line = [[Line alloc] init];
[line addCustomer:#"customer"];
NSLog(#"%#", [line printLine]);
NSLog(#"%#", [line removeCustomer:#"customer"]);
NSLog(#"%#", [line printLine]);
Edit:
I've updated my answer, passing the array as a parameter is not necessary, just initialize deliLine as a mutable array property.
For you first method, you could do the following,
- (NSString *)deliLineContents {
NSString *empty = #"The line is currently empty.";
NSMutableString *namesInQueue = [[NSMutableString alloc] init];
if(self.deliLine == nil || [self.deliLine count] == 0) {
return empty;
} else {
// Loop through your array and return a string of all the names
for (NSString *string in self.deliLine ) {
[namesInQueue appendString:string];
}
}
return [NSString stringWithString:namesInQueue];
For your second method, you're already pretty much there, maybe look up how to construct method signatures.
- (void)addNameToDeliLine:(NSString*)name {
[self.deliLine addObject:name];
}
For your third method, not sure if this meets your requirement, if not let me know.
- (NSString *)customerRemovedFromLine {
// I've making an assumption that you want to remove the first customer
NSString *servedCustomer = [self.deliLine objectAtIndex:0];
[self.deliLine removeObjectAtIndex:0];
return servedCustomer;
}
You probably don't need to pass deliLine around, just create it as a property and access it with self.deliLine. Anyway hope this helps, good luck.

Sending WatchKit Voice recognition's text to another interface controller

I am having an issue sending dictated text to another interface controller.
Here is my code:
- (IBAction)voiceRecognition {
[self presentTextInputControllerWithSuggestions:nil allowedInputMode:WKTextInputModePlain completion:^(NSArray *results) {
NSLog(#"results: %#", results);
NSString *wordKey = [NSString stringWithFormat:#"%#",results];
NSDictionary *dict = #{#"kWord":wordKey};
[self pushControllerWithName:#"Dictionary" context:dict];
}];
}
Logs:
Watch Extension[3185:2835671] results: ( Hello )
Getting data from other Interface controller:
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
NSDictionary *dict = (NSDictionary *)context;
[_word setText:dict[#"kWord"]];
NSLog(#"The Word is %#",[dict description]);
}
Logs:
Watch Extension[3185:2835671] The Word is {
kWord = "(\n Hello\n)";
}
Here is a screen shot that shows my problem:
The ( is supposed to show the word Hello. How can I fix this issue?
You used stringWithFormat to format an array as a string.
This took ["Hello"] and correctly converted it to the literal "(\n Hello\n)"
Because that string has a newline, it can't be displayed on a single line. Your Storyboard WKInterfaceLabel number of lines is likely set to 1, so it would only show the first line, which is (.
How can you fix this?
If you're only interested in the first word, use results.firstObject and pass that single word as the string value for your kWord key.
NSDictionary *dict = #{#"kWord": results.firstObject};
Otherwise, pass the entire array as the value, and have the destination interface controller handle the array of results as needed.
NSDictionary *dict = #{#"kWord": results};
You also may want to change the number of lines to show the entire dictation text, to handle the case where the text wouldn't fit on a single line.
Other options:
If you actually intended to send the dictated text as a single string of words, you can use
NSString *wordKey = [results componentsJoinedByString:#" "]

NSFormatter for BOOL

I have set up my simple Xcode project with a table that is binded to an array controller. It works fine if the array controller is full of entities with a string attribute. However I want to change the attribute to a BOOL and have the table show the string "true" or "false" based on the BOOL.
I have overrided the following two methods from NSFormatter:
-(NSString*) stringForObjectValue:(id)object {
//what is the object?
NSLog(#"object is: %#", object);
if(![object isKindOfClass: [ NSString class ] ] ) {
return nil;
}
//i'm tired....just output hello in the table!!
NSString *returnStr = [[NSString alloc] initWithFormat:#"hello"];
return returnStr;
}
-(BOOL)getObjectValue: (id*)object forString:string errorDescription:(NSString**)error {
if( object ) {
return YES;
}
return NO;
}
So the table gets populated with "hello" if the attribute is a string however if I switch it to a boolean, then the table gets populated with lots of blank spaces.
I don't know if this helps but on the line where I'm outputting the object, it outputs __NSCFString if the attribute is a string and "Text Cell" if I switch the attribute to a boolean. This is something else I don't understand.
Ok, it's not 100% clear what you're trying to do from the code, but first things first - BOOL is not an object, it's basically 0 or 1, so to place BOOL values into an array, you're probably best off using NSNumber:
NSNumber *boolValue = [NSNumber numberWithBool:YES];
and placing these into your array. Now you want to change your method:
-(NSString*) stringForObjectValue:(id)object {
NSNumber *number = (NSNumber *)object;
if ([number boolValue] == YES)
return #"true";
else
return #"false";
}
There's a few things here - for example, you want to avoid passing around id references if you can (if you know all your objects in the NSArray are NSNumber, you shouldn't need to).

How can I get an NSString value from a "(void)" method into a "(BOOL)" method in Objective-C?

I want to get the value of "city" into "CurrentLocation".
- (void)reverseGeocoder:(MKPlacemark *)placemark {
NSString *city = [myPlacemark.addressDictionary objectForKey:(NSString*) kABPersonAddressCityKey];
}
- (BOOL)fetchAndParseRSS {
NSString *currentLocation; // I want 'city' here.
return YES;
}
Why are your returning void from your reverseGeocoder message? I would have written this like this:
- (NSString*)reverseGeocoder:(Placemark*)myPlacemark
{
// assuming myPlacemark is holding a reference to the dictionary (so no need to retain)
NSString *city = [myPlacemark.addressDictionary objectForKey:kABPersonAddressCityKey];
return city;
}
-(BOOL)fetchAndParseRss
{
// you need to get myPlacemark from somewhere, presumably from the geocode request?
Placemark * myPlacemark = [self getPlacemark];
NSString * CurrentLocation = [self reverseGeocoder:myPlacemark];
}
In this code I am assuming Placemark is a class with a addressDictionary NSDictionary defined as a property.
If you really need that message to return a void* then you would cast from a NSString* to void* and then back again.
- (void*)reverseGeocoder:(Placemark*)myPlacemark
{
// assuming myPlacemark is holding a reference to the dictionary (so no need to retain)
NSString *city = [myPlacemark.addressDictionary objectForKey:kABPersonAddressCityKey];
return (void*)city;
}
Then cast it back to an NSString when you assign it (not sure why you would do this):
-(BOOL)fetchAndParseRss
{
// you need to get myPlacemark from somewhere, presumably from the geocode request?
Placemark * myPlacemark = [self getPlacemark];
NSString * CurrentLocation = (NSString*)[self reverseGeocoder:myPlacemark];
}