I've been struggling a lot trying to translate this code from Objective-C
NSDictionary * options = [NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMid] forKey:UIPageViewControllerOptionSpineLocationKey];
...to Swift
var options:NSDictionary = NSDictionary.dictionaryWithObjects(UIPageViewControllerSpineLocation.Mid, forKeys: UIPageViewControllerOptionSpineLocationKey, count: 0);
Unfortunately it doesn't work and I don't know why!
Here's what XCode's output reported:
Cannot invoke 'dictionaryWithObjects' with an argument list of type '(UIPageViewControllerSpineLocation, for keys: NSString!, count: IntegerLiteralConvertible)'
Can someone help me?
Thanks
how about just
let options = [UIPageViewControllerOptionSpineLocationKey: UIPageViewControllerSpineLocation.Mid];`
the problem you are facing is that the constructor NSDictionary.dictionaryWithObjects -- a) doesn't exist, b) that enums aren't AnyObject, c) that count is 0 but should be 1
let o = UIPageViewControllerSpineLocation.Mid.toRaw() //toRaw makes it conform to AnyObject
let k = UIPageViewControllerOptionSpineLocationKey
let options = NSDictionary(object: o, forKey: k)
Related
There is a particular case where I can't find the correct solution on how to cast a block defined in Objective C to a closure in Swift, so that I can execute it in Swift. For other cases using #escaping helped when having another block/closure being passed to a closure. But unfortunately not in this case.
Block type definitions in Objective C:
typedef void (^ViewModelUpdatedBlock)(GetValueForKeyPathBlock);
typedef id (^GetValueForKeyPathBlock)(NSString * keyPath);
Declaration of a block in Objective C:
someNSMutableDictionary[kViewModelUpdatedBlockKey] = ^(GetValueForKeyPathBlock getValueBlock) { ... }
When I try to use one of these blocks in Swift I can't find the correct way to cast it. I tried:
let viewModelUpdatedBlock = someNSMutableDictionary[kViewModelUpdatedBlockKey] as? ViewModelUpdatedBlock // = nil
let viewModelUpdatedBlock = someNSMutableDictionary[kViewModelUpdatedBlockKey] as? (GetValueForKeyPathBlock?)->() // = nil
let viewModelUpdatedBlock = someNSMutableDictionary[kViewModelUpdatedBlockKey] as? (GetValueForKeyPathBlock)->() // = nil
let viewModelUpdatedBlock = someNSMutableDictionary[kViewModelUpdatedBlockKey] as? (#escaping GetValueForKeyPathBlock)->() // = nil
Please help!
Previously in Objective-C, I would be able to do something like:
NSInteger count = 100;
NSString *text = [NSString stringWithFormat:#"count: %#", #(count)];
Objective-C had introduced the concept of autoboxing primitive literals so I didn't have to deal with %d, %ld, etc. It'll automatically convert the primitive literal into an NSObject which the formatter to parse as a %#.
In swift, is there something similar we can do?
let count: Int = 100
let text = String.init(format: "count of %#", count)
The above crashes because count is not a pointer to an object.
I know I can do inline parameter injection like:
let text = "count of \(count)"
But due to localization purposes, localizing the string format needs to happen before updating the parameters, which the code immediately above can't do.
Use Foundation types and bridge to NSNumber?
let count1: NSNumber = 100 // 100
let count2: NSNumber = 0.0 // 0
let count3: NSNumber = 2.73 // 2.73
let text = String(format: "count of %# %# %#", count1, count2, count3) // "count of 100 0 2.73"
That's really what "autoboxing" does, it wraps a primitive type in an Objective-C NSNumber object.
Doesn't quite answer the question, but I worked around the problem by wrapping my parameter with String(…), e.g.
let count: Int = 100
let text = String.init(format: "count of %#", String(count))
Update: an equivalent implementation to the above:
let count: Int = 100
let text = String.init(format: "count of %#", "\(count)")
Here's how I usually accomplish this: I just use a placeholder for the localization and swap it out after. So my strings files would look like this:
//English
"Could not read <name>" = "Could not read <name>."
//Spanish
"Could not read <name>" = "No puede leer <name>."
And my code would look like this:
//assume you have a fileName variable
var localizedString = NSLocalizedString("Error reading <name>", comment: "Error message when an object could not be read.")
localizedString = localizedString.replacingOccurrences(of: "<name>" with: fileName)
Instead of using an already-localized fileName, as I have in my example above, you could easily swap the placeholder for something like "\(count)". Just make sure that you localize the dropped-in value so that it displays nicely when put together with the text.
I have this Obj-C code:
What is need is to transform it to the Swift code.
(so far I did manage to rewrite C code to Swift, however, this is some kind of callback and sadly, I have not found any way to successfully transform it)
GPUImageRawDataOutput *rawDataOutput = [[GPUImageRawDataOutput alloc] initWithImageSize:CGSizeMake(640.0, 480.0) resultsInBGRAFormat:YES];
_rawDataOutput = rawDataOutput; // __unsafe_unretained instance variable
[rawDataOutput setNewFrameAvailableBlock:^{
GLubyte *outputBytes = [_rawDataOutput rawBytesForImage];
NSInteger bytesPerRow = [_rawDataOutput bytesPerRowInOutput];
NSLog(#"Bytes per row: %d", bytesPerRow);
NSData *dataForRawBytes = [NSData dataWithBytes:outputBytes length:/* I can't figure out how to get the length of the GLubyte pointer */];
[_targetUIImageView setImage:[UIImage imageWithData:dataForRawBytes]]; // An instance UIImageView
}];
Coding blind from cellphone. Give it a try with some help of compiler
let rawDataOutput = GPUImageRawDataOutput(CGSizeMake(640.0, 480.0),resultsInBGRAFormat:true)
self.rawDataOutput = rawDataOutput
rawDataOutput.setNewFrameAvailableBlock({(frame) IN
let outputBytes = self.rawDataOutput.rawBytesForImage
let bytesPerRow = self.rawDataOutput.bytesPerRowInOutput
print("Bytes per row \(bytesPerRow)")
let dataForRawBytes = NSData(bytes:outputBytes ,length:outputBytes.count)
self.targetUIImageView.setImage(UIImage(imageWithData:dataForRawBytes))
})
Getting an error here. Racking my brain. Tried all sorts of combinations.
Cannot find an initializer for type 'NSDictionary' that accepts an argument list of type '(object:(Int), forKey: CFString!)'
// configure the pixel format - Obj-C
// videoOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey, nil];
// Swift
videoOutput.videoSettings = NSDictionary(object: Int(kCVPixelFormatType_32BGRA), forKey:kCVPixelBufferPixelFormatTypeKey)
update: Swift 5.7
videoOutput.videoSettings = [
kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)
]
This has been changed in Swift 4.x, with the following working for me:
captureVideoDataOutput.videoSettings =
[kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_32BGRA]
It looks like the type would be [String: Int].
Actually, looking in the Xcode docs, it says that the value can either be a single number or an array. If it's an array then the type would be [String: [Int]].
So you should be able to say:
let aVideoSetting: [String: Int] =
[kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_32BGRA]
videoOutput.videoSettings = aVideoSetting
I'm still not 100% with the interoperability of Cocoa types and Swift types, so that might not be perfect, but it's close.
You could also rewrite your code to create an NSDictonary in swift syntax:
let aPixelFormat = NSNumber(int: kCVPixelFormatType_32BGRA)
let settingsDict = NSDictionary(aPixelFormat
forKey: "numberWithUnsignedInt:kCVPixelFormatType_32BGRA")
I have a class category wrote in Objective C. I need use this in Swift. But I don't know how to declare this to call.
var vcfPart: NSDictionary = [kSKPSMTPPartContentTypeKey:"video/quicktime;\r\n\tx-unix-mode=0644;\r\n\tname=\"video.mp4\"", kSKPSMTPPartContentTypeKey:"attachment;\r\n\tfilename=\"video.mp4\"", kSKPSMTPPartContentDispositionKey: self.rep ,kSKPSMTPPartMessageKey:"base64", kSKPSMTPPartContentTransferEncodingKey: "8bit"]
data is of type NSData. I need encode this with NSData+Base64Additions https://github.com/kailoa/iphone-smtp/blob/master/Classes/NSData%2BBase64Additions.m
in objective c call:
NSDictionary * vcfPart3 = [NSDictionary dictionaryWithObjectsAndKeys:#"video/quicktime;\r\n\tx-unix-mode=0644;\r\n\tname=\"video.mp4\"",kSKPSMTPPartContentTypeKey,
#"attachment;\r\n\tfilename=\"video.mp4\"",kSKPSMTPPartContentDispositionKey, [data encodeWrappedBase64ForData], kSKPSMTPPartMessageKey, #"base64", kSKPSMTPPartContentTransferEncodingKey, nil];
I don't know how to declare this in Swift with an extension..
How can use this in Swift?
Thanks!
Extensions can't contain stored properties, as I'm sure the compiler has already informed you. If this is actually a constant, express it as a computed property and you'll be fine.
In other words, this is illegal in an extension:
let i = 4
But this is legal:
var i : Int {
return 4
}