How to correctly initialize an UnsafePointer in Swift? - swift

I'm trying to use CTFontCreatePathForGlyph(font: CTFont?, glyph: CGGlyph, transform: CConstPointer<CGAffineTransform>):
let myFont = CTFontCreateWithName("Helvetica", 12, nil)
let myGlyph = CTFontGetGlyphWithName(myFont, "a")
let myTransform = CGAffineTransformIdentity
But how do I correctly pass myTransform to CTFontCreatePathForGlyph?
I've tried creating a myTransformPointer to pass to the function like so:
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer().initialize(newvalue: myTransform)
but I get this error:
Playground execution failed: error: <REPL>:20:76: error: '()' is not convertible to 'UnsafePointer<CGAffineTransform>'
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer().initialize(newvalue: myTransform)
so then I tried explicitly naming the type:
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer<CGAffineTransform>().initialize(newvalue: myTransform)
and then I get a different error:
Playground execution failed: error: <REPL>:20:95: error: could not find an overload for 'init' that accepts the supplied arguments
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer<CGAffineTransform>().initialize(newvalue: myTransform)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The auto-complete suggests this should work?

The simplest solution is using withUnsafePointer function:
let myFont = CTFontCreateWithName("Helvetica", 12, nil)
let myGlyph = CTFontGetGlyphWithName(myFont, "a")
var myTransform = CGAffineTransformIdentity
var path = withUnsafePointer(&myTransform) { (pointer: UnsafePointer<CGAffineTransform>) -> (CGPath) in
return CTFontCreatePathForGlyph(myFont, myGlyph, pointer)
}
The initialize is not a constructor. You would have to alloc a new memory using UnsafePointer<T>.alloc, then initialize and then dealloc. Function withUnsafePointer does that all for you.
Note that myTransform cannot be a constant (var not let) otherwise you cannot use it for an inout param (&myTransform).

Related

Cannot find 'strideofValue' in scope

I am getting:
Cannot find 'strideofValue' in scope
For below code:
public static func isDebuggerAttached() -> Bool {
var info = kinfo_proc()
var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var size = strideofValue(info)
let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
assert(junk == 0, "sysctl failed")
return (info.kp_proc.p_flag & P_TRACED) != 0
}
How can I fix the logic?
I tried stride(ofValue:), but that just causes another strange issue:
Type of expression is ambiguous without more context
(With strange I mean that, it should say something like, function exists but not with ofValue label)
There is no strideofValue function in Swift 5, replace strideofValue(info) with MemoryLayout.stride(ofValue: info).

Swift 4, keyPath get error: cannot assign to immutable expression of type 'Any'

public struct Person {
var fid: Int
var name: String
}
public struct Contact {
var fid: Int
var name: String
}
var pks = [\Person.fid, \Person.name]
var cks = [\Contact.fid, \Contact.name]
var p = Person(fid: 10, name: "hello")
var c = Contact(fid: 11, name: "test")
c[keyPath: cks[0]] = p[keyPath: pks[0]]
I want copy Contact's values to Person use swift 4 keyPath. Get an
error: cannot assign to immutable expression of type 'Any'
I don't understand why?
c[keyPath: cks[0] as! WritableKeyPath<Contact, Int>] = p[keyPath: pks[0]] as! Int
will work. bug how can I do like this:
pks.indices.forEach { index in
let pk = pks[index]
let ck = cks[index]
c[keyPath: ck] = p[keyPath: pk]
}
I'm hitting the same issue but the problem seems to be that it cannot infer writeable types when you mix them:
var mixed = [\Person.fid, \Person.name] // [PartialKeyPath<Person>]
var ids = [\Person.fid, \Person.sid] // [ReferenceWriteableKeyPath<Person, Int]
var mixedIds = [\Person.fid, \Contact.fid] // [AnyKeyPath]
var strings = [\Person.firstName, \Person.surname] // [ReferenceWriteableKeyPath<Person, String>]
In theory this would work:
let person = Person()
person[keyPath:strings[0]] = strings[1]
There seems to be no way to use Swift 4 KeyPath functionality on dynamic types. The compiler needs to be able to infer the types at compile time, not run time. The error you are receiving is telling you just that - compiler can't infer value type and so can't guarantee the value can be changed.

Objects in Swift: Value of 'Object' has no member

Here's my doozy.
I've got this lovely little function in a file called functions.swift
//functions.swift
func latestActiveGoal() -> Object {
let realm = try! Realm()
let currentGoal = realm.objects(Goal).filter("Active == 1").sorted("CreatedOn").last
return currentGoal!
}
which returns a Goal object. (A Goal might be wanting to lose weight, or stop being so inept at Swift).
In a different view controller, I want to access this object. Here's what I'm trying:
//viewController.swift
#IBOutlet weak var aimText: UILabel!
let funky = functions()
func getGoals(){
var currentGoal = funky.latestActiveGoal()
print(currentGoal)
aimText.text = currentGoal.Title
}
The print(CurrentGoal) output shows this:
Goal {
id = 276;
Title = Goal Title;
Aim = Aim;
Action = Nothing;
Active = 1;
CreatedOn = 2016-02-12 00:14:45 +0000;
}
aimText.text = currentGoal.Title and aimText = currentGoal.Title both throw the error:
Value of 'Object' has no member 'Title'
By printing the contents of the object, I can see the data, but can't figure out how. Any help greatly appreciated.
As the error message said, currentGoal is a value of Object type which doesn't have member Title.
This is because function latestActiveGoal returns Object instead of Goal. You just need to make it return Goal by change the return type:
func latestActiveGoal() -> Goal {
Just replace your functions with below code.
It will works perfect.
This fuction will check if goal available, then only it will return.
func latestActiveGoal() -> Object? {
let realm = try! Realm()
let currentGoals = realm.objects(Goal).filter("Active == 1").sorted("CreatedOn")
if currentGoals.count > 0 {
return currentGoals.last;
}
return nil;
}
Your getGoals method will be as follow.
func getGoals(){
if let currentGoalObject = funky.latestActiveGoal() {
print(currentGoalObject)
let goal = currentGoalObject as! Goal
print(goal.Title)
aimText.text = goal.Title
}
}

Nested Swift Dictionaries

I want to initialize a dictionary with a dictionary nested inside like this:
var a = [Int:[Int:Float]]()
a[1][2] = 12
But I get an error:
(Int:[Int:Float]) does not have a member named 'subscript'
I've hacked at a variety of other approaches, all of them running into some kind of issue.
Any idea why this doesn't work?
You can create your own 2D dictionary like this:
struct Dict2D<X:Hashable,Y:Hashable,V> {
var values = [X:[Y:V]]()
subscript (x:X, y:Y)->V? {
get { return values[x]?[y] }
set {
if values[x] == nil {
values[x] = [Y:V]()
}
values[x]![y] = newValue
}
}
}
var a = Dict2D<Int,Int,Float>()
a[1,2] = 12
println(a[1,2]) // Optional(12.0)
println(a[0,2]) // nil
The point is you access the element via a[x,y] instead of a[x][y] or a[x]?[y].
It's giving you that error because your first subscript returns an optional so it may return a dictionary or nil. In the case that it returns nil the second subscript would be invalid. You can force it to unwrap the optional value by using an exlamation point.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]![2]
If you aren't positive that a[1] is non-nil you may want to safely unwrap with a question mark instead.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]?[2]
You can also assign using this method. (As of Beta 5)
var a = [Int:[Int:Float]]()
a[1] = [Int: Float]()
a[1]?[2] = 12.0
a[1]?[2] //12.0
Another way to do it is with an extension to the standard dictionary:
extension Dictionary {
mutating func updateValueForKey(key: Key, updater: ((previousValue: Value?) -> Value)) {
let previousValue = self[key]
self[key] = updater(previousValue: previousValue)
}
}
Example:
var a = [Int:[Int:Float]]()
a.updateValueForKey(1) { nestedDict in
var nestedDict = nestedDict ?? [Int:Float]()
nestedDict[2] = 12
return nestedDict
}

How do you initialize NSXMLDocument with an XML string in Swift?

I'm trying to acquire values from an xml string, but being new to Swift I can't figure out how to initialize the NSXMLDocument object. I'm trying:
var xmlString:String = "<?xml version=\"1.0\"><results><item1><name>Something</name><price>10.99</price></item1></results>"
var xml:NSXMLDocument = NSXMLDocument(xmlString)
I'm getting the error "Cannot find an overload for 'init' that accepts the supplied arguments". I've tried converting the string to NSData but I end up with the same error:
var nsData:NSData = xmlString.dataUsingEncoding(NSUTF8StringEncoding)
var xml:NSXMLDocument = NSXMLDocument(nsData)
NSXMLDocument doesn't contain an initializer than only takes a string as a parameter. There is initWithXMLString:options:error: though, which should solve your problem. Something like:
let xmlString = "<?xml version=\"1.0\"><results><item1><name>Something</name><price>10.99</price></item1></results>"
var error: NSError?
let xml = NSXMLDocument(XMLString: xmlString, options: 0, error: &error)