Objective-C to Swift translation issue - objective-c

I'm trying to translate this simple line of code to Swift, but can't figure out how to write it:
AVCaptureConnection *videoConnection = nil;
I've tried:
let videoConnection: AVCaptureConnection = nil
let videoConnection: AVCaptureConnection = false
var videoConnection:AVCaptureConnection = AVCaptureConnection()
videoConnection = nil
var videoConnection:AVCaptureConnection = AVCaptureConnection()
videoConnection = false
var videoConnection:AVCaptureConnection = AVCaptureConnection()
videoConnection.active = false
var videoConnection:AVCaptureConnection = AVCaptureConnection()
videoConnection.active = nil
Any suggestions on how to write this is Swift would be appreciated.

If you want to "initialize" something with nil it has to be an Optional.
So
var videoConnection: AVCaptureConnection? = nil
or
var videoConnection: AVCaptureConnection?
would be right.

I believe it would be:
let videoConnection: AVCaptureConnection = UnsafePointer<Int8>.null()
Since Swift sort of conceals pointers from you (except that objects are really pointer references to the objects) and direct pointer manipulation, you sometimes have to contort yourself a bit. :)

Related

Casting Objective C blocks in Swift

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!

transform Objective C code of a class "GPUImageRawDataOutput" to Swift

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))
})

Troubles initializing NSDictionary in Swift

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)

How to convert NSUUID to NSData

I need to get NSData from vendorIdentifier without converting to NSString, clear bytes.
How to convert NSUUID using getUUIDBytes: to NSData?
NSUUID *vendorIdentifier = [[UIDevice currentDevice] identifierForVendor];
uuid_t uuid;
[vendorIdentifier getUUIDBytes:uuid];
NSData *vendorData = [NSData dataWithBytes:uuid length:16];
Use this to get the vendorIdentifier as Data (Swift 4):
var uuidBytes = UIDevice.current.identifierForVendor!.uuid
let uuidData = NSData(bytes: &uuidBytes, length: 16) as Data
Keep in mind to guard against UIDevice.current.identifierForVendor being nil as the documentation says.
Original answer (Swift 2 Version):
var uuidBytes: [UInt8] = [UInt8](count: 16, repeatedValue: 0)
UIDevice.currentDevice().identifierForVendor!.getUUIDBytes(&uuidBytes)
let uuidData = NSData(bytes: &uuidBytes, length: 16)
Swift 3 Version:
let vendorId = UIDevice.current.identifierForVendor!
let uuidBytes = Mirror(reflecting: vendorId.uuid).children.map { $0.1 as! UInt8 }
let data = Data(bytes: uuidBytes)

How do I find all the property keys of a KVC compliant Objective-C object?

Is there a method that returns all the keys for an object conforming to the NSKeyValueCoding protocol?
Something along the lines of [object getPropertyKeys] that would return an NSArray of NSString objects. It would work for any KVC-compliant object. Does such a method exist? I haven't found anything in searching the Apple docs so far.
Thanks,
G.
#import "objc/runtime.h"
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
NSString *propertyType = [NSString stringWithUTF8String:propType];
}
}
free(properties);
Use class_getPropertyList. That will tell you all the #properties of the object.
It won't necessarily list every KVC-compliant property, because any method that takes no arguments and returns a value is a valid KVC-compliant getter. There's no 100%-reliable way for the runtime to know which ones behave as properties (e.g., -[NSString length]) and which ones behave as commands (e.g., -[NSFileHandle readDataToEndOfFile]).
You should be declaring your KVC-compliant properties as #properties anyway, so this shouldn't be too big of a problem.
There is no such method as the KVO system does not require objects/classes to register with it which properties they support KVO for. Any key could potentially support KVO, the only way to know is from the author's documentation.
And of course, there is no guarantee that an #property will support KVO; it's quite possible to write a property that doesn't (and may be necessary sometimes). So, getting a list of a class's #propertys and then assuming they're KVO-compliant would be a dangerous choice in my opinion.
You need a getPropertyType function. See this post: Get an object attributes list in Objective-C
For Swift onlookers, you can get this functionality by utilising the Encodable functionality. I will explain how:
Conform your object to Encodable protocol
class ExampleObj: NSObject, Encodable {
var prop1: String = ""
var prop2: String = ""
}
Create extension for Encodable to provide toDictionary functionality
public func toDictionary() -> [String: AnyObject]? {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
guard let data = try? encoder.encode(self),
let json = try? JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)), let jsonDict = json as? [String: AnyObject] else {
return nil
}
return jsonDict
}
Call toDictionary on your object instance and access keys property.
let exampleObj = ExampleObj()
exampleObj.toDictionary()?.keys
Voila! Access your properties like so:
for k in exampleObj!.keys {
print(k)
}
// Prints "prop1"
// Prints "prop2"