I am refactoring to use ARC in my project and can not figure out this problem for the life of me!
I don't know where I got the code from.
screenshot of error http://img341.imageshack.us/img341/972/xcode.png"screenshot of error"
http://img341.imageshack.us/img341/972/xcode.png
The problem is that you are not using bridged casting. You have to use bridging to cast between C types and Objective-C types:
[UIView beginAnimations:#"earthquake" context:(__bridge void *)itemView];
When casting from a C pointer type to an Objective-C type:
UIView * item = (__bridge UIView *)context;
Related
Since recently when I try to pass an array of CLLocation from an Objective-c module to a Swift one I get:
fatal error: NSArray element failed to match the Swift Array Element
type
This is how I call the functions:
routeLine = [PreloadedLine lineWithLoadedPath:preloadedPath
key:lineKey
andNotification:(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)];
and here is the Swift signature for the function:
class func lineWithLoadedPath(path: [CLLocation]?,
key:String?,
andNotification notification:Bool)->Line?
And this is the Objective-c signature for it:
+ (Line * __nullable)lineWithLoadedPath:(NSArray<CLLocation *> * __nullable)path
key:(NSString * __nullable)key
andNotification:(BOOL)notification;
Believe the error message. Something that isn't a CLLocation is getting into the NSArray.
So, on the Objective-C side, you are saying:
[PreloadedLine lineWithLoadedPath:preloadedPath ...
...but preloadedPath is an NSArray with stuff in it that isn't all CLLocations, so on the Swift side, the app blows up.
I also ported the latter class to Swift along with its hierarchy and this problem got away by itself.
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).
I am trying to update some code for XCode 6.1 / Yosemite. It's a bit weird because it's a macro, but essentially it looks like:
dispatch_block_t blk = ^{ [[self globalEventsHandler] someMethod self]; };
if([NSThread isMainThread]) blk();
else dispatch_async(dispatch_get_main_queue(), blk);
This is causing compilation problems. I have already set OS_OBJECT_USE_OBJC=0 per GCD guide in my preprocessor settings, since right now I'm not interested in modernizing the code.
The first is Implicit conversion of block pointer type 'void (^)(void)' to C pointer type 'dispatch_block_t' (aka 'void *') requires a bridged cast. I can accept the suggest fix for this and get:
dispatch_block_t blk = (__bridge dispatch_block_t)^{ [[self globalEventsHandler] someMethod self]; };
if([NSThread isMainThread]) blk();
else dispatch_async(dispatch_get_main_queue(), blk);
but now I get a new error: Called object type 'dispatch_block_t' (aka 'void *') is not a function or function pointer. And on that I'm stuck.
Questions:
Is there a way to call dispatch_block_t directly now? I have found the original code pattern in a few older blog posts, so I suspect it is (was) common.
Is __bridge the correct way to do this? There seem to be other options related to dispatch_retain and friends that may be appropriate.
I feel like I'm missing a fundamental concept here, which would be very likely since I'm quite inexperienced with OSX development.
For bonus points: how would you get this working without disabling OS_OBJECT_USE_OBJC?
That code snippet is totally ok with Xcode 6.1 with OS X SDK 10.10. However, these compile error messages are odd.
Implicit conversion of block pointer type 'void (^)(void)' to C pointer type 'dispatch_block_t' (aka 'void *') requires a bridged cast
Called object type 'dispatch_block_t' (aka 'void *') is not a function or function pointer.
dispatch_block_t should be the following in dispatch/object.h.
typedef void (^dispatch_block_t)(void);
But these error messages say dispatch_block_t is the same as void *. Did you typedef dispatch_block_t yourself instead of including Foundation/Foundation.h or dispatch/dispatch.h? You'd better search dispatch_block_t typedef in your code.
I have seen code statements that use '(ClassName *)' to reference certain objects, like in UITableViewCell *myCell = (UITableViewCell*)[self.view viewWithTag:1];.
I have no idea what this means or how it works and I would like to increase my understanding of this concept.
I have also seen that the same code is also used in method declaration and would like to understand if this uses the same concept and if not, how is it different, e.g.
-(IBAction)myAction:(id)sender;
That serves as a typecast. It converts the type of the pointer to the type within the parentheses. In this case, it is converting a UIView instance (the result of `viewWithTag:) to an instance of UITableViewCell.
In ObjC, an object to object typecast does not result in a type conversion. That is to say - there is no new instance created. Additionally, typecasting an object performs no dynamic type checking when performing a dynamic downcast (unlike dynamic_cast in C++ or typecasting in Java, where an exception may be thrown).
Because -viewWithTag: returns a UIView (or NSView on OS X), a typecast is used to tell the compiler "It's OK - I know this type returned is a UITableViewCell instance". Using the typecast allows you to downcast from UIView to its subclass UITableViewCell in the assignment expression to the variable, which allows you to use the object as a UITableViewCell with the compiler matching the message or variable with the type. Without the typecast, you would logically be using it as or assigning it to a UIView (or one of its superclasses), and the compiler would complain if you tried to use methods implemented by subclasses of the instance. For example - you could not successfully use the variable to access the UITableViewCell.accessoryView property without either a typecast, type erasure, or a compiler warning or error. The typecast is the least evil in this case.
Now in the case of - (IBAction)myAction:(id)sender;, id is an untyped ObjC object. It has a special distinction in that it requires no typecast. For example:
- (IBAction)myAction:(id)sender
{
NSString * currentTitle = nil;
currentTitle = sender.currentTitle; // << May be ambiguous to the compiler because `id` is not fully typed
UIButton * button = sender; // << OK assign id to variable of arbitrary ObjC object type
currentTitle = button.currentTitle; // << OK
UIButton * castButton = (UIButton*)sender; // << although unnecessary, some people use this form.
currentTitle = castButton.currentTitle; // << OK
...
NSObject * object = button; // << OK. upcast from button to object. compiler knows it is an NSObject without typecasting.
Personally, I just wrap it all into the parameter -- which is fine for ObjC objects in method declarations as long as you know the type of the parameter which is being passed:
- (IBAction)myAction:(UIButton *)pButton
{
NSString * currentTitle = pButton.currentTitle; // << OK
...
Is just a typecast necessary to suppress the compiler warning.
In other words its saying to the compiler [self.view viewWithTag:1] is an UITableViewCell. Without that cast the compiler would complain that UIView is not a UITableViewCell.
I came across a strange problem today. I created a subclass of UIView and added only 1 method to the template code provided by xcode.
#interface FloatView : UIView {
}
- (void)floatTest:(CGFloat)x;
#end
- (void)floatTest:(CGFloat)x {
NSLog(#"float was %f", x);
}
Then in my appDelegate I had code like this:
UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Pretty simple, right? What should this print out? I thought it would something like "10.0000", but no, it prints out "0.000000".
I wrestled with this for hours, trying to figure out what I was doing wrong, and then I changed the code in my appDelegate to
FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Only then, did it print out the expected "10.0000". Why is this so? I've declared FloatView as a subclass of UIView, shouldn't I be able to assign a FloatView object to a UIView pointer without problems?
Even though floatView was declared a pointer to a UIView, it's really a floatView and it should be able to handle the floatTest message? Am I totally off base here?
Actually, polymorphism is working as expected. If it didn't work, nothing would have been printed (in your example, 0.0000 is being printed). The thing is, while your instance actually responds to testFloat:10.0f message, since the compiler can't statically see the method declaration (as UIView class doesn't declare such a method), it assumes that your method takes ... as argument and returns id.
When CGFloat is passed to a method that expects variable number of arguments (...), it's promoted to double. Thus, the receiving method is passed a double argument and thinks it's a float and it doesn't get printed correctly.
You can verify this behavior by changing NSLog line to:
NSLog(#"%f", *(double*)&x);
When the compiler sends the message to FloatView* rather than a UIView*, it can find the exact signature of the method. It can see it really expects CGFloat and doesn't promote the argument to double. As a result, it works correctly.
Additionally, if UIView* contained the method declaration that took a CGFloat, the compiler would call the method appropriately. To summarize, this is not a polymorphism issue; it's a missing method signature issue.