I'm trying to convert the following from Objective-C to Swift:
-(int)fillBuffer:(void *)buffer {
SInt16* p = (SInt16 *)buffer;
// ...
p[33] = 0
}
I've come to understand that (void *) maps to the UnsafeMutableRawPointer? type in Swift.
However, I'm missing a step in converting it into something that can take the subscript operation.
So far, I've got this:
func fill(buffer: UnsafeMutableRawPointer!) -> Int {
buffer[33] = 0
}
Looking for feedback and advice. Thanks in advance!
Casting a void pointer to a typed pointer
SInt16* p = (SInt16 *)buffer;
is done in Swift with assumingMemoryBound():
func fillBuffer(_ buffer: UnsafeMutableRawPointer) -> Int {
let p = buffer.assumingMemoryBound(to: Int16.self)
// ...
p[33] = 0
return 0
}
Test code:
var i16Array = Array(repeating: Int16(99), count: 40)
print(i16Array[33]) // 99
_ = fillBuffer(&i16Array) // passes a pointer to the element storage to the function
print(i16Array[33]) // 0
Related
So I am trying to implement the Superpowered library in Swift, and am getting stuck around initialisation with a callback. How would I convert that line:
__unsafe_unretained Superpowered *self = (__bridge Superpowered *)clientdata;
into Swift?
Here is the simplified Objective C implementation:
#implementation Superpowered {
SuperpoweredIOSAudioIO *audioIO;
SuperpoweredBandpassFilterbank *filters;
unsigned int samplerate;
}
static bool audioProcessing(void *clientdata, float **buffers, unsigned int inputChannels, unsigned int outputChannels, unsigned int numberOfSamples, unsigned int samplerate, uint64_t hostTime) {
__unsafe_unretained Superpowered *self = (__bridge Superpowered *)clientdata;
if (samplerate != self->samplerate) {
self->samplerate = samplerate;
};
// Update position.
self->lastNumberOfSamples = numberOfSamples;
return false;
}
- (id)init {
self = [super init];
if (!self) return nil;
samplerate = 44100;
audioIO = [[SuperpoweredIOSAudioIO alloc] initWithDelegate:(id<SuperpoweredIOSAudioIODelegate>)self preferredBufferSize:12 preferredMinimumSamplerate:44100 audioSessionCategory:AVAudioSessionCategoryRecord channels:2 audioProcessingCallback:audioProcessing clientdata:(__bridge void *)self];
[audioIO start];
return self;
}
And here is the start of my Swift version:
func bridge<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
}
func bridge<T : AnyObject>(ptr : UnsafeMutableRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
}
open class EchoesEngine: NSObject, CLLocationManagerDelegate, SuperpoweredIOSAudioIODelegate {
public var audioIO:SuperpoweredIOSAudioIO
static var lastNumberOfSamples:UInt32!
static var samplerate:UInt32!
override init() {
super.init()
audioIO = SuperpoweredIOSAudioIO.init(delegate: self, preferredBufferSize: 12, preferredMinimumSamplerate: 44100, audioSessionCategory: AVAudioSessionCategoryPlayAndRecord, channels: 2, audioProcessingCallback: EchoesEngine.audioProcessingCallback, clientdata: bridge(obj: self))
…
}
#objc static let audioProcessingCallback : #convention(c) (UnsafeMutableRawPointer?, UnsafeMutablePointer<UnsafeMutablePointer<Float>?>?, UInt32, UInt32, UInt32, UInt32, UInt64) -> Bool = {
(clientdata, buffers, inputChannels, outputChannels, numberOfSamples, _samplerate, hostTime) in
/*
let unsafePointer = Unmanaged<EchoesEngine>.fromOpaque(clientdata!).takeUnretainedValue()
let pointer = AutoreleasingUnsafeMutablePointer<EchoesEngine>(unsafePointer)
*/
self = bridge(ptr: clientdata!)
if samplerate != _samplerate {
samplerate = _samplerate
}
lastNumberOfSamples = numberOfSamples
return false
}
So I discovered that in this context the self I was trying to cast to is actually a new variable providing an __unsafe_unretained reference to self, as passed to the initialiser for SuperpoweredIOSAudioIO.
This answer provided me with almost everything I needed. Swift 3.3 changes a couple of things, and this is what I ended up with:
func bridge<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
}
func bridge<T : AnyObject>(ptr : UnsafeMutableRawPointer?) -> T {
return Unmanaged<T>.fromOpaque(ptr!).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
}
I searched on google and on SO but didn't find any useful help for this issue.
I'm trying to translate this code from objective-c to swift:
- (void)metaTitleUpdated:(NSString *)title {
NSLog(#"delegate title updated to %#", title);
NSArray *chunks = [title componentsSeparatedByString:#";"];
if ([chunks count]) {
NSArray *streamTitle = [[chunks objectAtIndex:0] componentsSeparatedByString:#"="];
if ([streamTitle count] > 1) {
titleLabel.text = [streamTitle objectAtIndex:1];
}
}
}
so far i have translated it to this:
func metaTitleUpdated(input: String) {
println("delegate title updated to \(title)")
let chunks: NSArray = title!.componentsSeparatedByString(";")
if (chunks.count) {
let streamTitle = chunks .objectAtIndex(0) .componentsSeparatedByString(";")
if (streamTitle.count > 1) {
titleLabel.text = streamTitle.objectAtIndex(1)
}
}
}
but i always get the error "Type 'Int' does not conform to protocol 'BooleanType'" in the line: if (chunks.count) {
What does cause this error? Is the rest of the code in swift correct or are there any other errors?
chunks.count has the type Int, but the if statement requires a boolean expression.
This is different from (Objective-)C, where the controlling expression of an if statement can have any scalar type and is compared with zero.
So the corresponding Swift code for
if ([chunks count]) { ... }
is
if chunks.count != 0 { ... }
I solved the answer by myself.
func metaTitleUpdated(title: String) {
var StreamTitle = split(title) {$0 == "="}
var derRichtigeTitel: String = StreamTitle[1]
titleLabel.text = derRichtigeTitel
println("delegate title updated to \(derRichtigeTitel)")
}
So I'm trying to convert some obj-c code into swift but I'm stuck on a part of it.
How can I do something like this in swift?
- (void)sometMethod:(NSString *)s {
NSString * crlfString = [s stringByAppendingString:#"\r\n"];
uint8_t *buf = (uint8_t *)[crlfString UTF8String];}
The real problem is this line
uint8_t *buf = (uint8_t *)[crlfString UTF8String];
What do you want to do with the UTF-8 buffer? Generally, it is more convenient to convert the string directly to an NSData object. But you can also translate your Obj-C code one by one to Swift. Here are both variants:
import Foundation
func appendCRLFAndConvertToUTF8_1(s: String) -> NSData {
let crlfString: NSString = s.stringByAppendingString("\r\n")
let buffer = crlfString.UTF8String
let bufferLength = crlfString.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let data = NSData(bytes: buffer, length: bufferLength)
return data;
}
func appendCRLFAndConvertToUTF8_2(s: String) -> NSData {
let crlfString = s + "\r\n"
return crlfString.dataUsingEncoding(NSUTF8StringEncoding)!
}
let s = "Hello 😄"
let data1 = appendCRLFAndConvertToUTF8_1(s)
data1.description
let data2 = appendCRLFAndConvertToUTF8_2(s)
data2.description
data1 == data2
And if you want to iterate over the UTF-8 code units and not deal with a buffer, use something like:
for codeUnit in String.utf8 {
println(codeUnit)
}
I was wondering if it's possible to determine the class or primitive type of an Objects properties. Getting all properties names and values is pretty easy. SO answer
So is there any way to get the properties class type while the property hast no value or nil value?
Example Code
#interface MyObject : NSObject
#property (nonatomic, copy) NSString *aString;
#property (nonatomic, copy) NSDate *aDate;
#property NSInteger aPrimitive;
#end
#implementation MyObject
#synthesize aString;
#synthesize aDate;
#synthesize aPrimitive;
- (void)getTheTypesOfMyProperties {
unsigned int count;
objc_property_t* props = class_copyPropertyList([self class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = props[i];
// Here I can easy get the name or value
const char * name = property_getName(property);
// But is there any magic function that can tell me the type?
// the property can be nil at this time
Class cls = magicFunction(property);
}
free(props);
}
#end
After searching through Apples Documentation about objc Runtime and according to this SO answer I finally got it working. I just want to share my results.
unsigned int count;
objc_property_t* props = class_copyPropertyList([MyObject class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = props[i];
const char * name = property_getName(property);
NSString *propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
const char * type = property_getAttributes(property);
NSString *attr = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString componentsSeparatedByString:#","];
NSString * typeAttribute = [attributes objectAtIndex:0];
NSString * propertyType = [typeAttribute substringFromIndex:1];
const char * rawPropertyType = [propertyType UTF8String];
if (strcmp(rawPropertyType, #encode(float)) == 0) {
//it's a float
} else if (strcmp(rawPropertyType, #encode(int)) == 0) {
//it's an int
} else if (strcmp(rawPropertyType, #encode(id)) == 0) {
//it's some sort of object
} else {
// According to Apples Documentation you can determine the corresponding encoding values
}
if ([typeAttribute hasPrefix:#"T#"]) {
NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)]; //turns #"NSDate" into NSDate
Class typeClass = NSClassFromString(typeClassName);
if (typeClass != nil) {
// Here is the corresponding class even for nil values
}
}
}
free(props);
Inspired by the ObjC answer by #arndt-bieberstein I have written a solution in Swift 3 (probably very similar - if not same - in earlier versions of Swift). You can find it on Github I am trying to make a pod of it but I am having issues getting pob lib lintto work with the Swift 3 code (CLI xcodebuild or Xcode 8 related problem probably.) Anyhow, the class method func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? can extract the name and types of any Swift class that inherits from NSObject.
The work horse of the project are these methods, but checkout the full code on Github:
func getTypesOfProperties(in clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}
func getTypeOf(property: objc_property_t) -> Any {
guard let attributesAsNSString: NSString = NSString(utf8String: property_getAttributes(property)) else { return Any.self }
let attributes = attributesAsNSString as String
let slices = attributes.components(separatedBy: "\"")
guard slices.count > 1 else { return getPrimitiveDataType(withAttributes: attributes) }
let objectClassName = slices[1]
let objectClass = NSClassFromString(objectClassName) as! NSObject.Type
return objectClass
}
func getPrimitiveDataType(withAttributes attributes: String) -> Any {
guard let letter = attributes.substring(from: 1, to: 2), let type = primitiveDataTypes[letter] else { return Any.self }
return type
}
func getNameOf(property: objc_property_t) -> String? {
guard let name: NSString = NSString(utf8String: property_getName(property)) else { return nil }
return name as String
}
It can extract the NSObject.Type of all properties which class type inherits from NSObject such as NSDate (Swift3: Date), NSString(Swift3: String?) and NSNumber, however it is store in the type Any (as you can see as the type of the value of the Dictionary returned by the method). This is due to the limitations of value types such as Int, Int32, Bool. Since those types do not inherit from NSObject, calling .self on e.g. an Int - Int.self does not return NSObject.Type, but rather the type Any. Thus the method returns Dictionary<String, Any>? and not Dictionary<String, NSObject.Type>?.
You can use this method like this:
class Book: NSObject {
let title: String
let author: String?
let numberOfPages: Int
let released: Date
let isPocket: Bool
init(title: String, author: String?, numberOfPages: Int, released: Date, isPocket: Bool) {
self.title = title
self.author = author
self.numberOfPages = numberOfPages
self.released = released
self.isPocket = isPocket
}
}
guard let types = getTypesOfProperties(inClass: Book.self) else { return }
for (name, type) in types {
print("'\(name)' has type '\(type)'")
}
// Prints:
// 'title' has type 'NSString'
// 'numberOfPages' has type 'Int'
// 'author' has type 'NSString'
// 'released' has type 'NSDate'
// 'isPocket' has type 'Bool'
You can also try to cast the Any to NSObject.Type, which will succeed for all properties inheriting from NSObject, then you can check the type using standard == operator:
func checkPropertiesOfBook() {
guard let types = getTypesOfProperties(inClass: Book.self) else { return }
for (name, type) in types {
if let objectType = type as? NSObject.Type {
if objectType == NSDate.self {
print("Property named '\(name)' has type 'NSDate'")
} else if objectType == NSString.self {
print("Property named '\(name)' has type 'NSString'")
}
}
}
}
If you declare this custom == operator:
func ==(rhs: Any, lhs: Any) -> Bool {
let rhsType: String = "\(rhs)"
let lhsType: String = "\(lhs)"
let same = rhsType == lhsType
return same
}
You can then even check the type of value types like this:
func checkPropertiesOfBook() {
guard let types = getTypesOfProperties(inClass: Book.self) else { return }
for (name, type) in types {
if type == Int.self {
print("Property named '\(name)' has type 'Int'")
} else if type == Bool.self {
print("Property named '\(name)' has type 'Bool'")
}
}
}
LIMITATIONS
I have not yet been able to give this project support for when the value types are optionals. If you have declared a property in you NSObject subclass like this: var myOptionalInt: Int? my solution will not work, because the method class_copyPropertyList can't find those properties.
Does anyone have a solution for this?
I have an object, and I want to list all the selectors to which it responds. It feels like this should be perfectly possible, but I'm having trouble finding the APIs.
This is a solution based on the runtime C functions:
class_copyMethodList returns a list of class methods given a Class object obtainable from an object.
#import <objc/runtime.h>
[..]
SomeClass * t = [[SomeClass alloc] init];
int i=0;
unsigned int mc = 0;
Method * mlist = class_copyMethodList(object_getClass(t), &mc);
NSLog(#"%d methods", mc);
for(i=0;i<mc;i++)
NSLog(#"Method no #%d: %s", i, sel_getName(method_getName(mlist[i])));
/* note mlist needs to be freed */
I think usually you'll want to do that in the console, instead of cluttering your code with debug code. This is how you can do that while debugging in lldb:
(Assuming an object t)
p int $num = 0;
expr Method *$m = (Method *)class_copyMethodList((Class)object_getClass(t), &$num);
expr for(int i=0;i<$num;i++) { (void)NSLog(#"%s",(char *)sel_getName((SEL)method_getName($m[i]))); }
This is also possible with Swift:
let obj = NSObject()
var mc: UInt32 = 0
let mcPointer = withUnsafeMutablePointer(&mc, { $0 })
let mlist = class_copyMethodList(object_getClass(obj), mcPointer)
print("\(mc) methods")
for i in 0...Int(mc) {
print(String(format: "Method #%d: %s", arguments: [i, sel_getName(method_getName(mlist[i]))]))
}
Output:
251 methods
Method #0: hashValue
Method #1: postNotificationWithDescription:
Method #2: okToNotifyFromThisThread
Method #3: fromNotifySafeThreadPerformSelector:withObject:
Method #4: allowSafePerformSelector
Method #5: disallowSafePerformSelector
...
Method #247: isProxy
Method #248: isMemberOfClass:
Method #249: superclass
Method #250: isFault
Method #251: <null selector>
Tested with the 6s simulator running iOS 9.2, Xcode Version 7.2 (7C68).
Taking inspiration from JAL's answer, in Swift you can do:
extension NSObject {
var __methods: [Selector] {
var methodCount: UInt32 = 0
guard
let methodList = class_copyMethodList(type(of: self), &methodCount),
methodCount != 0
else { return [] }
return (0 ..< Int(methodCount))
.flatMap({ method_getName(methodList[$0]) })
}
}
ARC realization
SomeClass *someClass = [[SomeClass alloc] init];
//List of all methods
unsigned int amountMethod = 0;
Method *methods = class_copyMethodList(someClass, &amountMethod);
for (unsigned int i = 0; i < amountMethod; i++) {
Method method = methods[i];
printf("\t method named:'%s' \n", sel_getName(method_getName(method)));
}
free(methods);
Something like this should work (just put it in the object you're curious about). For example if you have an object that's a delegate and want to know what 'hooks' are available this will print out messages to give you that clue:
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("Selector: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
Note that I discovered this in the iPhone Developer's Cookbook so I can't take credit! For example output I get from a UIViewController that implements the protocols <UITableViewDelegate, UITableViewDataSource>:
Selector: tableView:numberOfRowsInSection:
Selector: tableView:cellForRowAtIndexPath:
Selector: numberOfSectionsInTableView:
Selector: tableView:titleForHeaderInSection:
Selector: tableView:titleForFooterInSection:
Selector: tableView:commitEditingStyle:forRowAtIndexPath:
Selector: sectionIndexTitlesForTableView:
Selector: tableView:sectionForSectionIndexTitle:atIndex:
...
...
etc.,etc.
If you want to also get the selectors for the super classes you can loop through like this:
Class c = [myObject class];
while (c != nil) {
int i = 0;
unsigned int mc = 0;
Method* mlist = class_copyMethodList(c, &mc);
NSLog(#"%d methods for %#", mc, c);
for(i = 0; i < mc; i++) {
const char* selName = sel_getName(method_getName(mlist[i]));
NSLog(#"Method #%d: %s", i, selName);
}
free(mlist);
c = [c superclass];
}