Extra argument in call when calling JSONSerialization.JSONObjectWithData [duplicate] - swift

This question already has answers here:
Swift: Extra argument 'error' in call
(3 answers)
Closed 4 years ago.
let data = json.data(using: String.Encoding.utf8)!
let wrapper = JSONSerialization.JSONObjectWithData(data, options:nil, error:nil) as NSDictionary
Error is thrown on this line
let wrapper = JSONSerialization.JSONObjectWithData(data, options:nil, error:nil) as NSDictionary

what do i do?
Remove the extra argument. The Swift version of the method is declared like this:
class func jsonObject(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any
As you can see, it throws an error instead of taking an error parameter. There's even a sidebar in the documentation labeled Handling Errors in Swift: that explains a bit about how to use this method with try/catch to handle errors, and there's a link to more information on the topic.

Related

Invocation-based Undo Manager in Swift [duplicate]

This question already has answers here:
NSUndoManager casting NSUndoManagerProxy crash in Swift code
(2 answers)
Closed 5 years ago.
I'm having trouble adopting the more complex invocation-based approach to undo registration in Swift (based on NSHipster article here. Apple's docs still have all sample code in Objective-C, and the semantics are very different for the invocation setup).
My NSDocument subclass Document has the following method that operates on the model objects, which I wish to make undoable:
func rename(object: Any, to newName: String) {
// This is basically a protocol that requires implementing:
// var name: String { get set }
//
guard var namedObject = object as? EditorHierarchyDisplayable else {
return
}
// Register undo:
let undoController = undoManager?.prepare(withInvocationTarget: self) as? Document
undoController?.rename(object: namedObject, to: namedObject.name)
undoManager?.setActionName("Rename \(namedObject.localizedClassName)")
// Perform the change:
namedObject.name = newName
}
What I have found out is that undoController above is nil, becuase the atempted cast to Document fails. If I remove the cast (and comment out the call to undoController.rename(...), prepare(withInvocationTarget:) returns the folowing object:
(lldb) print undoController
(Any?) $R0 = some {
payload_data_0 = 0x00006080000398a0
payload_data_1 = 0x0000000000000000
payload_data_2 = 0x0000000000000000
instance_type = 0x000060800024f0d8
}
(lldb) print undoController.debugDescription
(String) $R1 = "Optional(NSUndoManagerProxy)"
(lldb)
What am I missing?
I think the basic confusion is that prepare(withInvocationTarget:) returns a proxy object (that happens to be the undo manager itself, but that's an implementation detail). The idea is that you send this proxy object the same message(s) you send to undo the action, but instead of executing them (because it's not the actual object), it internally captures those invocations and saves them for later.
So your code should really start out something like this:
let selfProxy: Any = undoManager?.prepare(withInvocationTarget: self)
This works great in Objective-C because the "catchall" type (id) has very lax type checking. But the equivalent Any class in Swift is much more stringent and does not lend itself to the same technique, if at all.
See Using NSUndoManager and .prepare(withInvocationTarget:) in Swift 3

Closure on collection that doesn't need to return anything [duplicate]

This question already has an answer here:
Map a void (non-returning function) over an array
(1 answer)
Closed 6 years ago.
I'm trying to write a function to add attributes to an NSAttributedString. I have passed in a dictionary to the function like...
tag attributes
[String : [String : Any]]
These (the tag and the attributes) will then be passed into another function to add the attributes inside the given tag.
func addAttributes(attributes: [String: Any], forTag tag: String)
I can just do...
for (tag, attributes) in dictionary
but is there a closure way of doing this?
If I use flat map...
dictionary.flatMap { addAtritbutes(attributes: $1, insideTag: $0) }
Then it complains that I'm not returning anything/using the result of the call. Is there a function that will allow me to do this without warnings?
Thanks
You can use forEach closure for that.
dictionary.forEach {
addAtritbutes(attributes: $0.value, insideTag: $0.key)
}

Swift 3: How to display an image using URL with API [duplicate]

This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 6 years ago.
I tried to show an image but the following error occurs:
error : fatal error: unexpectedly found nil while unwrapping an
Optional value
var imageURL:UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string:"http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg")
let data = NSData(contentsOfURL:url!)
if data!= nil {
imageURL.image = UIImage(data:data!)
}
}
From apples docs:
Important
Do not use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.
Instead, for non-file URLs, consider using the dataTaskWithURL:completionHandler: method of the NSURLSession class. See URL Session Programming Guide for details.
Maybe consider using Alamofire for this task?
Alamofire.request(.GET, "http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg").response { (request, response, data, error) in
self.imageURL.image = UIImage(data: data, scale:1)
}

NSMapTable "Generic parameter 'KeyType' could not be inferred" [duplicate]

This question already has an answer here:
Declare "NSMapTable StrongObject" in Swift 3
(1 answer)
Closed 6 years ago.
The following line is giving me the compiler error "generic parameter 'KeyType' could not be inferred":
fileprivate var delegatesMap = NSMapTable.strongToWeakObjects()
I tried being more explicit by saying:
fileprivate var delegatesMap:MapTable<Key,Value> = NSMapTable.strongToWeakObjects()
But I then Xcode doesn't recognize "Key"
How do I go about fixing this?
EDIT: I would like my Key to be of type String, and my Value to be of type MenuActionDelegate(class protocol)
You may need to write something like this:
fileprivate var delegatesMap = NSMapTable<NSString, MenuActionDelegate>.strongToWeakObjects()
The generic parameters KeyType and ValueType need to be AnyObject, so you cannot directly put String there, also you need some explicit casting as NSString.
And the value type MenuActionDelegate needs to an #objc-protocol.
Or else you may need to write something like this:
var delegatesMap = NSMapTable<NSString, AnyObject>.strongToWeakObjects()
And use it as:
let theDelegate = delegatesMap.object(forKey: "delegateName" as NSString) as! MenuActionDelegate

What to use in place of stringByAppendingPathComponent in Swift 2 [duplicate]

This question already has answers here:
stringByAppendingPathComponent is unavailable
(11 answers)
Closed 7 years ago.
I have just installed Xcode 7 with the new Swift 2, and I now have 50+ errors saying that "stringByAppendingPathComponent" is unavailable, and that I should use "URLByAppendingPathComponent" instead. I have been setting all of my texture properties like so:
let dropTexture = SKTexture(image: UIImage(
contentsOfFile:NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent(
"P04_rainDrop1.png"))!)
I have been doing this so they do not stay in memory when the SKScene is changed and it has been working perfectly. However directly replacing "URLByAppendingPathComponent" does not fix the errors.
How can I change this to fix the error and get the same SKTexture?
All you have to do is cast to NSString to recover stringByAppendingPathComponent, like this:
let dropTexture = SKTexture(image: UIImage(
contentsOfFile:(NSBundle.mainBundle().resourcePath! as NSString).stringByAppendingPathComponent(
"P04_rainDrop1.png"))!)
As Leo Dabus rightly says, you can save yourself from all that casting by adding an extension to String. However, you should not, as he suggests, call NSString(string:), which generates an extra string. Just cast:
extension String {
func stringByAppendingPathComponent(pathComponent: String) -> String {
return (self as NSString).stringByAppendingPathComponent(pathComponent)
}
}