I am junior Swift user but on this stage of life I need use serial connection in my project.
when I looking for availeble port ,I see them without problem but when try to send something I have problem why?
I have problem with ORSSerial this my code:
func applicationDidFinishLaunching(_ aNotification: Notification) {
let portEvString = ORSSerialPortManager.shared().availablePorts
let pathString = portEvString[0].path
let portClass = SerialController(path:pathString)
portClass.open()
portClass.SendString(data: "hello")
// Insert code here to initialize your application
RunLoop.current.run()
}
class SerialController : NSObject, ORSSerialPortDelegate {
var port : ORSSerialPort?
init(path: String){
port = ORSSerialPort(path: path)
port?.close()
}
func open(){
port?.baudRate=9600
port?.delegate=self
port?.open()
}
func close(){
port?.delegate=nil
port?.close()
}
func SendString(data: String){
let dataa = Data(data.utf8)
port?.send(dataa)
}
func serialPortWasOpened(serialPort: ORSSerialPort!) {
print("PORT IS OPEN....")
}
func serialPortWasClosed(serialPort: ORSSerialPort!) {
print("PORT IS CLOSE")
}
func serialPort(serialPort: ORSSerialPort!, didReceiveData data: NSData!) {
print(NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue))
}
func serialPortWasRemovedFromSystem(_ serialPort: ORSSerialPort!) {
print("PORT REMOVED")
}
func serialPort(serialPort: ORSSerialPort!, didEncounterError error: NSError!) {
print("PORT ERR \(error)")
}
}
I believe the primary problem is that you don't store the instance of SerialController in a strong reference, so it gets deallocated immediately after you call SendString() on it. You need to store it in a property like so:
var serialController: SerialController?
func applicationDidFinishLaunching(_ aNotification: Notification) {
let availablePorts = ORSSerialPortManager.shared().availablePorts
let pathString = availablePorts[0].path
serialController = SerialController(path:pathString)
serialController?.open()
serialController?.SendString(data: "hello")
}
Beyond that problem, there are a number of things about this code that you should fix. The things that stick out most:
Don't call RunLoop.current.run() in applicationDidFinishLaunching(_:). You rarely need to manually run the run loop, and you definitely don't need to here.
As documented in ORSSerialPort, you must release any strong references to the port in your implementation of serialPortWasRemovedFromSystem(_:). That means in that method, you need to do port = nil.
The force unwrap operators (!) scattered through this code make me wonder if you're using an old version of ORSSerialPort, from before I added nullability annotations. Please make sure you're using the latest version (2.0.2 as of this writing).
Use more descriptive names for your variables. For example, portEvString is not a good name, because it's difficult to understand (what does "Ev" mean?), and its type is not a string, it's an array of ORSSerialPort objects (ie. [ORSSerialPort].
Your SendString method shouldn't start with a capital letter. Function (and method) names in Swift should always start with a lowercase letter.
After the disable SandBox, everything is OK.
Related
I've been reading a book about Golang and it's common use global vars to expose the result of private functions. Why not to expose public functions? here's an exemple.
I am comming from java and this is tricky for me. What are advantages of using global vars like these?
EDIT: I notice that without parenthesis I am not calling the function. It's just a pointer. Is it a good pratice or does have some advantages?
package config
import "time"
var (
GetHTTPServerAddress = getHTTPServerAddress
GetHTTPReadTimeout = getHTTPReadTimeout
GetHTTPWriteTimeout = getHTTPWriteTimeout
)
func getHTTPServerAddress() string {
return getConfigString("http.server_address")
}
func getHTTPReadTimeout() time.Duration {
return getConfigDuration("http.read_timeout")
}
func getHTTPWriteTimeout() time.Duration {
return getConfigDuration("http.write_timeout")
}
I've been reading a book about Golang and it's common use global vars to expose the result of private functions.
To expose the result of private functions, not the functions themselves; your example is a little off. Without the parens you're exposing the function itself.
package main
import (
"fmt"
)
var(
FooItself = foo // (func() string)(0x108b720)
FooResult = foo() // "bar"
)
func main() {
fmt.Printf("%#v\n", FooItself)
fmt.Printf("%#v\n", FooResult)
}
func foo() string {
return "bar"
}
Try it.
Your example would look more like this.
package config
var (
// You wouldn't call the variable "Get*", that exposes
// the implementation.
HTTPServerAddress = getHTTPServerAddress()
HTTPReadTimeout = getHTTPReadTimeout()
HTTPWriteTimeout = getHTTPWriteTimeout()
)
func getHTTPServerAddress() string {
return getConfigString("http.server_address")
}
func getHTTPReadTimeout() time.Duration {
return getConfigDuration("http.read_timeout")
}
func getHTTPWriteTimeout() time.Duration {
return getConfigDuration("http.write_timeout")
}
But no private methods are necessary. Just run the function and assign it to a global.
package config
var (
HTTPServerAddress = getConfigString("http.server_address")
HTTPReadTimeout = getConfigDuration("http.read_timeout")
HTTPWriteTimeout = getConfigDuration("http.write_timeout")
)
Now people can use config.HTTPServerAddress and the details remain hidden without requiring an extra layer of methods.
And yes, it can be done on the result public functions. A very common example is error codes. For example, in net/http.
var (
ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body")
ErrHijacked = errors.New("http: connection has been hijacked")
)
In Java you might create an exception subclass for each type of error. In Go you make a single object, share it as a global variable, and everything references that object.
The purpose is to hide the details from the user. The exact wording of the error can change, but as long as everyone is referencing net.http.ErrBodyNotAllowed their code will still work.
io/fs has a more complex example exposing the result of its private methods.
var (
ErrInvalid = errInvalid() // "invalid argument"
ErrPermission = errPermission() // "permission denied"
ErrExist = errExist() // "file already exists"
ErrNotExist = errNotExist() // "file does not exist"
ErrClosed = errClosed() // "file already closed"
)
func errInvalid() error { return oserror.ErrInvalid }
func errPermission() error { return oserror.ErrPermission }
func errExist() error { return oserror.ErrExist }
func errNotExist() error { return oserror.ErrNotExist }
func errClosed() error { return oserror.ErrClosed }
Why use private method wrappers here? Why not ErrInvalid = oserror.ErrInvalid?
(I'm assuming) Go wants to keep oserror hidden, even from the documentation!
oserror is just making error objects to define its possible errors.
package oserror
import "errors"
var (
ErrInvalid = errors.New("invalid argument")
ErrPermission = errors.New("permission denied")
ErrExist = errors.New("file already exists")
ErrNotExist = errors.New("file does not exist")
ErrClosed = errors.New("file already closed")
)
If it's result of a function, it's probably something like static member initialization or perhaps even static final.
The example you linked suggests that it's some sort of config load procedure and values are exposed for global use.
Precomputing data is also not unheard of.
If you see function pointers, however, it could be done to enable mocking.
YMMV. Sometimes it's just an antipattern as well.
What am I doing wrong? I don't get this notification. I have this function:
#objc func onAutocorrection (_ notification: Foundation.Notification) {
Swift.print("\(notification)")
}
later in the same class I do use it as follows:
NotificationCenter.default.addObserver(
self,
selector: #selector(onAutocorrection(_:)),
name: NSSpellChecker.didChangeAutomaticCapitalizationNotification,
object: nil)
The addObserver is executed, but the function is never called even when the application is capitalising in an NSTextView.
Why? Many thanks in advance!
It looks like I misunderstood the notification. It is not meant to be triggered when automatic capitalisation happens but when the systems preference of your Mac is changing.
See the comment of ever helpful Willeke and see Notification of autocorrect
In order to get to the intended result of reacting to autocapitalisation did I implement this function in the NSTextViewDelegate:
public func textView(_ view: NSTextView, didCheckTextIn range: NSRange, types checkingTypes: NSTextCheckingTypes, options: [NSSpellChecker.OptionKey : Any] = [:], results: [NSTextCheckingResult], orthography: NSOrthography, wordCount: Int) -> [NSTextCheckingResult] {
if !range.contains(0){
return results
}
var newResult = [NSTextCheckingResult]()
for result in results {
if let textToChange = view.string[range].components(separatedBy: " ").first, let replacement = result.replacementString?.components(separatedBy: " ").first {
let firstLetterCap = textToChange.capitalizingFirstLetter()
if replacement == firstLetterCap {
continue //don't add to results
}
}
newResult.append(result)
}
return newResult
}
This function will prevent that the first character will be capitalised.
Ultimately, I check whether the capitalised version of the first word of the range that must include position "0" is equal to the first word of the replacement string. And if it is then I remove that result/suggestion from the result list.
I need UI tests for XCode project that is a platfrom for several products.
It means that some elements are custom for some products. For instance, they can have different colors, text styles, etc. from product to product, or the same element could be visible for one project, but hided for another one.
How can I configure my XCode UI tests to make them reusable for various products? I understand I need different schemas. But what about visability elements, for example? It seems I need to check it inside the UI test code? But I think it would be better to use any config file. Am I right? Does anyone have any ideas? I'd be grateful for all advices.
I recommend building out a suite of test helpers that you use in each of your products. These are generic, parameterized functions, such as logging a user in or adding an item to the shopping cart. Instead of hard coding your UI element representations in these helpers, parameterize the inputs. Then you can use them over and over.
func addItemToCart(named: String, saveButtonName: String)
func login(username: String, password: String, submitButtonText: String)
func tapTableCell(imageNamed: String)
Once you create a basic scaffolding for navigation you can move on to assertion helpers. Leaving the complex logic in the helpers enables you to reuse them and keep your product-specific tests lean and readable.
func assertCurrentScreen(named: String)
func assertHighlightedCell(colorNamed: String)
func assertCartTotal(cents: String, containerIdentifier: String)
For all of these functions, I recommend adding two default parameters at the end to note the callers file and line number. If you make any custom assertions you can then pass these references in to show your failure at the callers line, not the helpers.
func assertScreen(titled: String, file: StaticString = #file, line: UInt = #line) {
if !XCUIApplication().navigationBars[titled].exists {
XCTFail("Item was not added to cart.", file: file, line: line)
}
}
I am using a function at the beginning of each test.
class SomeTestsClass: XCTestCase {
func testSomeTest() {
var externalConfigVariable_1 = "value for defult test"
var externalConfigVariable_2 = "value for defult test"
// here You use the external config to override
// the default test logc
if let testConfig = getConfig(for: self.name) {
// read config parameters here
externalConfigVariable_1 = testConfig["test_var_1"]
externalConfigVariable_2 = testConfig["test_var_2"]
// ..........
}
// use the variables as You like
// ......
}
}
extension XCTestCase {
public func getConfig(for name: String?) -> [String: Any]? {
let nameComponents = name?.replacingOccurrences(of: "-", with: "").replacingOccurrences(of: "[", with: "").replacingOccurrences(of: "]", with: "").components(separatedBy: " ")
if let fileName = nameComponents?.last {
let testBundle = Bundle(for: type(of: self))
guard let path = testBundle.url(forResource: fileName, withExtension: "JSON") else {
return nil
}
if let data = try? Data(contentsOf: path) {
if let testConfig = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String: Any] {
return testConfig
}
}
}
return nil
}
}
Here is an example JSON:
{
"test_var_1": "Some var",
"test_var_2": "Some other var"
}
Currently I'm working on my new App written with Swift 2.0. Today I faced two strange errors in Xcode beta 5. I'd love if someone with a previous beta version of Xcode can confirm if I'm right or not. I also could misunderstand something, so I'll appreciate any feedback.
Here is some example code that made me struggle a while:
// Frist bug
protocol SomeProtocol {
var someArray: [String] { get set } // #1 bug
}
extension SomeProtocol {
func someFunction(someString: String) {
self.someArray.append(someString) // #1: Immutable value of type '[String]' only has mutating members named 'append'
}
}
// Second bug
protocol SomeInterfaceProtocol {
var someBool: Bool { get set } // #2 bug
}
class SomeClass: SomeInterfaceProtocol {
var someBool: Bool = false
func returnInterface() -> SomeInterfaceProtocol {
return self
}
}
let someInstance = SomeClass()
// can't set the value
someInstance.returnInterface().someBool = true // #2: Cannot assign to property: function call returns immutable value
The first error can be solved if you add the modifier mutating before the extension func declaration like this:
mutating func someFunction(someString: String) {
I suspect that's a change in the language.
The other one puzzles me as well. At least, here's a work-around:
var c = someInstance.returnInterface()
c.someBool = true
I think the second one isn't a bug as well for the same reason that you can't modify an item in a dictionary directly, or that you can't change elem in for elem in array { ... }.
Something has to be saved to be able to change it. Because you're returning the protocol type, the compiler can't know whether it's a struct or a class, whereas if it's a struct the operation of changing it would have no effect because it's not persisted in any way and structs aren't passed by reference. That's why Thomas' workaround works. Maybe it'll work too if returnInterface returned a class instance, instead of the protocol type.
EDIT: Just tried it out: Indeed it works either if you return SomeClass instead of SomeInterfaceProtocol or if you change the protocol to a class protocol, as it can't be a struct
protocol SomeInterfaceProtocol : class {
var someBool: Bool { get set }
}
class SomeClass: SomeInterfaceProtocol {
var someBool: Bool = false
func returnInterface() -> SomeInterfaceProtocol {
return self
}
}
or
protocol SomeInterfaceProtocol {
var someBool: Bool { get set }
}
class SomeClass: SomeInterfaceProtocol {
var someBool: Bool = false
func returnInterface() -> SomeClass {
return self
}
}
both work
When compiling the following Swift code (in Sample.swift):
import Cocoa
class Sample {
func doSomething() {
var stringArray = Array<String>()
stringArray.append("AAA")
addToString(stringArray)
stringArray.append("CCC")
}
func addToString(myArray:Array<String>) {
myArray.append("BBB")
}
}
I get the following error on the line 'myArray.append("BBB")':
Immutable value of type 'Array<String>' only has mutating members named 'append'
How do I fix the code to allow a call to this mutable method?
Many thanks in advance
If you want to modify the array you have to specify it as in an inout parameter like this func addToString(inout myArray:Array<String>). Then when you call the function you have to add & in front of your argument to show that it can be modified by the function. Your code will look something like this:
class Sample {
func doSomething() {
var stringArray = Array<String>()
stringArray.append("AAA")
addToString(&stringArray)
stringArray.append("CCC")
}
func addToString(inout myArray:Array<String>) {
myArray.append("BBB")
}
}
You may want to take a look at in-out parameters on this page.