I am seeing this currently
expr self.attributedText = [(NSAttributedString *)([NSAttributedString alloc]) initWithString:#""];
error: <user expression 24>:1:75: no known method '-initWithString:'; cast the message send to the method's return type
self.attributedText = [(NSAttributedString *)([NSAttributedString alloc]) initWithString:#""];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
While creating a NSString works:
(lldb) expr str = [(NSString *)([NSString alloc]) init];
(__NSCFConstantString *) $92 = 0x00007fff8098cd68 #""
just telling NSAttributedString is not an Extension of/or inherited from NSString, instead it has a property called string
and if you can avoid the paranthesis if you do not need a cast.
(lldp) expr str = [[NSAttributedString alloc] initWithString:#""];
should just work
You can usually avoid the need to cast Foundation methods like this in the expression parser by importing the Foundation module in the debugger.
If you build your code by using the "modules import" form:
import Foundation;
and passing -fmodules when building the .o file (there's also an Xcode setting for this) then the debug info records that your code imported the Foundation module, and lldb will automatically import that.
If you don't use the module form, you can still get lldb to import the module by doing:
(lldb) expr #import Foundation
Doing either of those things, I can run your expression w/o extra casting.
Related
I want to create a wrapper around the NSURLSession and I found some nice code but was written in Swift.https://github.com/daltoniam/SwiftHTTP.But since I still write production code in Objective-C I started borrowing the idea of the above code, though I have hard time to understand the following code and translate to Objective-C (if needed).
I know I could use AFNetworking but this is not feasible due to architecture decisions when building a distributable framework.
The code:
/// encoding for the request.
public var stringEncoding: UInt = NSUTF8StringEncoding
// Somewhere in a method
var charset = CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
if request.valueForHTTPHeaderField(contentTypeKey) == nil {
request.setValue("application/x-www-form-urlencoded; charset=\(charset)",
forHTTPHeaderField:contentTypeKey)
}
request.HTTPBody = queryString.dataUsingEncoding(self.stringEncoding)
My Objective-C code:
#property (assign, nonatomic) NSUInteger stringEncoding;
// In this line I get a compiler warning and in runtime it crashes with BAD_EXC
CFStringEncoding cfStringEncoding = CFStringConvertIANACharSetNameToEncoding(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
if (![mutableRequest valueForHTTPHeaderField:ContentTypeKey])
{
[mutableRequest setValue:[NSString stringWithFormat:#"application/x-www-form-urlencoded; charset=%u", (unsigned int)cfStringEncoding] forHTTPHeaderField:ContentTypeKey];
}
mutableRequest.HTTPBody = [queryString dataUsingEncoding:self.stringEncoding];
Compiler warning:
Incompatible integer to pointer conversion assigning to 'CFStringEncoding' (aka 'unsigned long') from 'CFStringRef' (aka 'const struct __CFString *')
I don't have strong experience working with CFStringEncoding and CFString so I find it hard to translate the documentation.
Do I really need this conversion, and what is it's purpose?
Try using NSString instead:
NSString *charset =
(NSString *)CFStringConvertEncodingToIANACharSetName
(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
This is what typically was used before the Swift version, and as I recall AFNetworking used a similar method (if not the same).
Things like this drive me crazy when debugging:
(lldb) p self.bounds
error: unsupported expression with unknown type
error: unsupported expression with unknown type
error: 2 errors parsing expression
(lldb) p (CGRect)self.bounds
error: unsupported expression with unknown type
error: unsupported expression with unknown type
error: C-style cast from '<unknown type>' to 'CGRect' is not allowed
error: 3 errors parsing expression
(lldb) p [self bounds]
error: 'bounds' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (CGRect)[self bounds]
(CGRect) $1 = origin=(x=0, y=0) size=(width=320, height=238)
(lldb) You suck!
error: 'You' is not a valid command.
(lldb) …
Why did the first 3 attempts fail? Is there any simpler way to print self.bounds? Thanks.
You can access it by
p (CGRect)[view bounds]
or
p view.layer.bounds
view.bounds is actually view.layer.bounds
It seems that the type info of [UIView bounds] is not available to lldb
Starting from Xcode 6.3, we have a better solution. In short, you need to import UIKit for LLDB to know about these types:
expr #import UIKit. Check out this article to learn some tricks to make your life even easier.
You gonna love Xcode 6.3+
TLDR
(lldb) e #import UIKit
(lldb) po self.view.bounds
LLDB's Objective-C expression parser can now import modules. Any
subsequent expression can rely on function and method prototypes
defined in the module:
(lldb) p #import Foundation
(lldb) p NSPointFromString(#"{10.0, 20.0}");
(NSPoint) $1 = (x = 10, y = 20)
Before Xcode 6.3, methods and functions without debug information
required explicit typecasts to specify their return type. Importing
modules allows a developer to avoid the more labor-intensive process
of determining and specifying this information manually:
(lldb) p NSPointFromString(#"{10.0, 20.0}");
error: 'NSPointFromString' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (NSPoint)NSPointFromString(#"{10.0, 20.0}”);
(NSPoint) $0 = (x = 10, y = 20)
Other benefits of importing modules include better error messages,
access to variadic functions when running on 64-bit devices, and
eliminating potentially incorrect inferred argument types.
PS: If you also confuse p vs po
p == print == expression -- == e --
po == expression -O -- == e -O --
-- is the separator between command+flag vs inputs
-O flag is for invoking the object description method
With Xcode 6.3, we can import UIKit and then print the frame or bound of view
expr #import UIKit
p self.view.bounds
LLDB does not support dot notation for message sending when using p and that's why
p self.bounds
doesn't work, but
p [self bounds]
does.
(It actually supports it for objects when you use po, though)
Also, LLDB doesn't have type information of non-objects available at runtime, so you need to explicitly provide a type by casting the return value.
I don't know what was the context when you running this. But looks like lldb cannot find the type of self.
In order for lldb to evaluate self.bounds, it need to know the type of self is some Class has property bounds. It cannot assume self is ObjC type because you may call it under such context:
void test()
{
struct
{
int bounds;
} self;
}
so you get the error error: unsupported expression with unknown type
However, if you call it using [self bounds], lldb knows that self much be ObjC type because [] syntax only apply to ObjC type. But since the type of self is not clear, it still cannot evaluate the result of [self bounds] so you need to cast it to CGRect
Try with following expression,
p self.view.bounds.size.width
or use,
po self.view
p - Print is only uses to print normal/simple values
while,
po - Print Object works same as NSLog to print value of an object
I tried #an0's answer expr #import UIKit, but it didn't work.
Then I added a pch file, and add these lines of code in the file:
#ifndef PrefixHeader_pch
#define PrefixHeader_pch
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#endif /* PrefixHeader_pch */
Next, link the pch file to my project:
Run the app again, then I can use the dot notation in lldb console:
(lldb) po self.view.bounds
For how to add a pch file , see the answer here PCH File in Xcode 6
I have a special NSLog method swizzle that prints the current method as part of the log statement.
For Objective-C methods, I have a macro that uses: NSStringFromSelector(_cmd)
For non Objective-C methods, I have a second macro that uses __PRETTY_FUNCTION__ because _cmd is not defined.
I am now trying to use the same macro for both, so I am trying to test if it is defined and thought I could do so like this:
NSString *command = (&_cmd != nil ? NSStringFromSelector(_cmd) : [NSString stringWithCString:__PRETTY_FUNCTION__ encoding:NSUTF8StringEncoding])
but I am still getting some Use of undeclared identifier '_cmd' errors when the macro is used in non Objective-C methods. How can I do a runtime test do determine if _cmd is defined or not?
You cannot test at runtime whether _cmd is defined.
The __PRETTY_FUNCTION__ macro is defined in Objective-C methods. Just use __PRETTY_FUNCTION__ everywhere and don't try to use _cmd.
Example:
- (IBAction)mapWasTapped:(UITapGestureRecognizer *)sender {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
Here's the output:
2012-12-01 11:45:30.036 TestApp[92581:c07] -[MainViewController mapWasTapped:]
In Objective-C, I can write:
id pString = #"Hello, World.";
and the compiler will instantiate an NSString without me needing to explicitly call a factory method. However, NSString is really just a Foundation class and thus presumably not part of the actual Objective-C language definition.
So when I write #"String", how does the compiler know to build an NSString in particular, and not some other string-like object? In other words, where does the Objective-C language stop and the Foundation library start?
When you write Objective-C code outside of Cocoa or GNUStep environments, #"..." is not linked to NSString.
In this case, gcc provides an option for specifying a class associated to literal strings:
-fconstant-string-class=class-name
Use class-name as the name of the class to instantiate for each
literal string specified with the syntax "#"..."". The default
class name is "NXConstantString".
The #"" directive appears to be built-in to the objective-c compiler.
For instance, if you remove all #imports from your .m source file (& prefix header), the following line will be a syntax error:
NSString *string = #"ABCD"; // (Doesn't know anything about NSString class)
However, if you change the Foundation NSString type to the built-in void type, it will compile just fine:
void *string = #"ABCD";
So, even without Foundation's NSString definition, the compiler knows how to turn #"" into something that can become an NSString instance at runtime (it probably won't instantiate without Foundation, but the compiler doesn't seem to mind); Since it accepts the syntax without needing any external library definitions, the compiler sees #"" as part of the language.
Your code, however, won't be able to make use of any #"" instance without importing Foundation.h, so from the point of view of your program, #"" is part of the library.
Another interesting bit is that an Objective-C string literal (#"" notation) returns the same type as an explicitly instantiated NSString object:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
printf("string literal class: %s\n", object_getClassName(#"a string literal"););
NSString *str = [[NSString alloc] initWithUTF8String:"asdf"];
printf("explicit NSString class: %s", object_getClassName(str));
[pool drain];
return 0;
}
I vaguely remember that in other, older implementations of Objective-C, the string literal actually returned an object of a slightly different class, but that could be used interchangeably with NSString/NSCFString. Not totally sure on that part, though.
I am having trouble deciphering a "passing argument ... from distinct Objective-C type warning".
I have a constant string declared as:
extern NSString * const URL_1;
and defined as:
NSString * const URL_1 = #"http://someurl";
If I, say, assign that constant to an NSString as follows:
NSString *URL = nil;
...
URL = [[NSString alloc] initWithString:URL_1];
And pass this NSString as an argument to a function expecting an NSString:
ViewController *viewController = [[ViewController alloc] initWithURL:URL];
Function signature:
- (id)initWithURL:(NSString *)URL
I receive a warning that I am "passing argument 1 of 'initWithURL': from distinct Objective-C type"
As I understand it NSString objects are immutable once created, and I am assigning the value to the string once upon creation, so I don't understand why the constant nature of URL_1 should cause a problem.
I am sure I am being a donut here and have overlooked something simple! Please could someone help me resolve this warning? Many thanks in advance!
There are many methods in the system frameworks that are declared as:
- (id)initWithURL:(NSURL *)anURL;
And, of course, +alloc is declared as:
- (id) alloc;
Thus, when the compiler sees:
ViewController *viewController = [[ViewController alloc] initWithURL:URL];
The return type of the allocation is id and the compiler is likely seeing the above declaration and that causes the warning. Now, generally, the compiler would also warn that it found multiple signatures for the selector -- multiple signatures for that particular method name.
If it isn't, it is quite likely because you haven't imported ViewController.h into the file that contains the above line of code.
In short, do not declare a method with the same name as another method that takes a different type of argument.