Swift 4 using selector with Multiple Parameters [duplicate] - swift3

This question already has answers here:
Passing arguments to selector in Swift
(6 answers)
Attach parameter to button.addTarget action in Swift
(14 answers)
Closed 5 years ago.
I write with Swift 4 and try to write a function that send categoryId as action but I couldn't write .I think my syntax is wrong.If I write function without parameters its not a problem but I get error with parameters functions. Could you say me how to use selector?
#objc func sendCategoryIdToPackageSelectionVC(categoryId : Int){
MarketVC.categoryId = categoryId
self.performSegue(withIdentifier: "sequeGoToPackageSelection", sender: nil)
}
func addTapFeatures(){
taplabel1 = UITapGestureRecognizer(target: self, action: #selector(self.sendCategoryIdToPackageSelectionVC(categoryId:2)))
taplabel1?.cancelsTouchesInView = false
self.labelFirst.addGestureRecognizer(taplabel1!)
}
I get an error saying that the action selector doesn't refer to any objc method.

i think, you can't directly use selector to pass parameter.
try some thing like this
you should create an #objc method that calls handleTap(modelObj:myModelObj).
#objc func someMethod() { // name this properly!
handleTap(modelObj: myModelObj)
}
Then you can pass this as a selector:
#selector(someMethod)

Related

Change JSON serialization from camelCase to PascalCase [duplicate]

This question already has answers here:
JSON serializer Not Working After Upgrade To 3.6.2
(2 answers)
Closed 3 years ago.
After migrating my project from Core 2.1. to 2.2. I am having trouble with my Kendo widgets. Fields in the model are specified with PascalCase and the field names returned from the server in the JSON are using camelCase.
I've added DefaultContractResolver in Startup but JSON is still serialized in camelCase. Any workaround here?
services
.AddMvc(options => options.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
We had a similar problem with Syncfusion expecting PascalCase.
Until now the only solution we found is to create our own
PascalCasePropertyNamesContractResolver : DefaultContractResolver
Therein we just override the ResolvePropertyName to return the key as is.
Unfortunately we have to reference this ContractResolver in each Json-Return, like this:
return Json(new { result = result.Items, count = result.Count }, new JsonSerializerSettings { ContractResolver = new PascalCasePropertyNamesContractResolver () });
If there are better solutions coming up here: welcome and thanks in advance.

Struct field reverts [duplicate]

This question already has answers here:
How to set and get fields in struct's method
(3 answers)
Assign a new value to a struct field
(2 answers)
Closed 5 years ago.
I'm playing with Go a bit but found this weird situation while doing some tests.
I'm using method in a struct to send a variable to another method that should change a field, but when I check it at the end, the field goes back to the first value, which has me confused.
func (this TVManager) sendMessage(message string) {
fmt.Println("5", this.connector)
payload := map[string]string {
"id": "0",
"type": "request",
"uri": "ssap://system.notifications/createToast",
"payload": "{'message': 'This is a message'}"}
this.connector.sendCommand(payload)
fmt.Println("4", this.connector)
}
This is the method I'm testing, it calls sendCommand of connector.
func (this MockConnector) sendCommand(payload map[string]string) {
fmt.Println("0", this)
this.last_command = payload
this.value = true
fmt.Println("0", this)
}
Which in the mock object I'm using is simply changing the value of this struct fields.
manager.sendMessage("This is a message")
fmt.Println("1", connector)
assert.Equal(t, expected, connector.last_command, "Command should be equal")
But when I check it, it goes back to internal. I set some prints to try an d track the values and they change the values as expected, but then it reverts.
1 {false map[]}
5 {false map[]}
0 {false map[]}
0 {true map[uri:ssap://system.notifications/createToast payload:{'message': 'This is a message'} id:0 type:request]}
4 {false map[]}
1 {false map[]}
--- FAIL: TestTVManagerSendsNotificationDownToConnector (0.00s)
This is just a small program I'm going over to learn some Go, so I appreciate any help anybody could give me.
You are passing the structures by value. This works fine so long as you are not modifying the structure, but if you do modify it you are actually only modifying a copy. To make this work you need to use pointers to the structures you need to modify.
Instead of:
func (this MockConnector) sendCommand(payload map[string]string)
Use:
func (this *MockConnector) sendCommand(payload map[string]string)
Also, it is considered a bad idea to use this (or self) as a receiver name in Go, as a receiver is not the same thing as a this pointer/reference in other languages.
Another best practice, is if one method for a given type needs a pointer receiver, all methods for that type should have pointer receivers. This is so that the method set remains consistent no matter if the value is a pointer or not.
See method sets, and these FAQ answers for more information.

Swift Delegation: unexpectedly found nil while unwrapping an Optional value

Edit: Please note the question below discusses using delegation between
2 viewcontrollers that are also implemented in a UITabBarController.
I've done a fair bit of searching here and on YouTube, but haven't seen my issue replicated elsewhere. I'll keep it to the point.
I have 2 view controllers that I coded myself -not generated by XCode-; TabOneController, and TabTwoController
below are the coding for both...
import UIKit
class TabOneController: UIViewController{
private let instanceOfTabOneView = TabOneView()
var vc1Delegate: fromOneToTwo!
override func loadView() {
super.loadView()
view.addSubview(instanceOfTabOneView.buildTheVu())
view.backgroundColor = UIColor.white
runThisOnce()
}
func runThisOnce(){
vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController")
}
}
protocol fromOneToTwo{
func passTheValue(heroNameIs: String)
}
as for tab 2...
import UIKit
class TabTwoController: UIViewController, fromOneToTwo{
private let instanceOfTabTwoView = TabTwoView()
override func loadView() {
super.loadView()
view.addSubview(instanceOfTabTwoView.buildTheVu())
assignDelegateToSelf()
}
func assignDelegateToSelf(){
let instanceTabOne = TabOneController()
instanceTabOne.vc1Delegate = self
}
func passTheValue(heroNameIs:String){
instanceOfTabTwoView.txtFld.text = heroNameIs
}
}
I'm getting the following error at runtime -the app builds successfully-...
fatal error: unexpectedly found nil while unwrapping an Optional value
on the following line...
vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController")
When I comment out the above line, the app builds and runs successfully, but of course the app doesn't execute the delegation.
I kinda understand what the compiler is trying to tell me, that the
vc1Delegate
hasn't been instantiated -I guess-. But I searched under every rock, and can't seem to find how to get around this.
I'd appreciate any help or guidance. Sorry if my code seems immature, I'm new to Swift and programming in general. Thank you.
In a UITabBarController, the first tab is instantiating by default. The view controller initialization executes the loadView and finds a nil because the second tab did not initialize yet; this is normal behavior. My suggestion is making the delegate weak optional with the ? suffix and run the delegate code elsewhere. Also, always capitalize the first letter in class and protocol names.
weak var vc1Delegate: FromOneToTwo?
If this structure is mandatory, try with a custom notification observer instead.
First thing first, your error happens in line var vc1Delegate: fromOneToTwo! while you declared this delegate variable as not null but then calling passTheValue on it. A correct practice will be
var vc1Delegate: fromOneToTwo?
func runThisOnce(){
if let delegate = vc1Delegate {
vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController")
}
}
Secondly, you are not using delegate correctly. In the assignDelegateToSelf() function, you are creating a new instance of TabOneController
and then assign delegate. Instead, you need to find out the existing TabOneController instance and assign delegate.
I try this and worked add delegate = self in table cellforRowAt
like this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "ChapterPracticeTableViewCell") as! ChapterPracticeTableViewCell
cell.deligate = self
return cell
}

Swift 3. Argument Labels do not match error

I have just upgraded to Swift 3 and get an error on the following code that is within a UITableViewController.
The code is return segue from a form, and is intended to refresh the table inserting the new entry from the form. This worked fine on 2.2, and I have changed NSIndexPath to IndexPath
#IBAction func saveTripFormViewList(segue:UIStoryboardSegue){
trips = uiRealm.objects(Trip.self)
let indexPath = IndexPath(forRow: trips!.count - 1, inSection: 0)
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
The error I get is
Argument labels '(forRow:, inSection:)' do not match any available overloads
Any advice on how to resolve the error
In Swift 3 it's just IndexPath(row:section:).
FYI, IndexPath is a new value type (a struct) that does the same job as NSIndexPath (a class). (NSIndexPath's initializer has changed as well.) Also, I believe they're toll-free bridged, but don't quote me on that.

UIPanGestureRecognizer action method not called in Swift 3

I have set a pan gesture to an imageView, though it's action method never being called in swift 3.
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(panGesture:)))
panGesture.minimumNumberOfTouches = 1
imageview.addGestureRecognizer(panGesture)
the action method:
#objc func panGestureHandler(panGesture recognizer: UIPanGestureRecognizer) {
}
Am I missing anything?
Ok, seems dumb, but after debugging I've noticed that the imageView's userInteractionEnabled is set to false.
After adding this line imageview.isUserInteractionEnabled = true everything seems to be working properly.
You may try to use a function handler for you rUIPanGestureRecognizer like this.
func panGestureHandler(recognizer: UIPanGestureRecognizer) {
}