NilLiteralConvertible in Property setter - swift

In swift I have this:
///3.5.1.8 Range is ± 32,576 FPM, FPM of 32640 means max. Also can be invalid (nil)
var vVelcotiy: Int? {
get {
let ret : Int16 = decode12Bit2sCompliment(bytes[15], bytes[16], useEntireFirstByte: false)
return Int(ret * 64);
}
set {
if (bytes[15] == 8 && bytes[16] == 0) {
return nil
}
if let n = newValue {
let nv = n / 64
bytes[15] = (bytes[15] & 0xF0) | (UInt8(nv) >> 8)
bytes[16] = UInt8(nv)
} else {
bytes[15] = (bytes[15] & 0xF0) | 0xF8
bytes[16] = 0x00
}
}
}
I'm getting an error of type '()' does not conform to protocol 'NilLiteralConvertible' but I've declared my property as optional so I'm confused.
I'm hoping to be able to do:
var a : vVelocity = nil

Reading rintaro's answer and taking my comment into consideration, I think you've misplaced the first check in the setter, it looks like it belongs in the getter instead:
var vVelcotiy: Int? {
get {
if (bytes[15] == 8 && bytes[16] == 0) {
return nil
}
let ret : Int16 = decode12Bit2sCompliment(bytes[15], bytes[16], useEntireFirstByte: false)
return Int(ret * 64);
}
set {
if let n = newValue {
let nv = n / 64
bytes[15] = (bytes[15] & 0xF0) | (UInt8(nv) >> 8)
bytes[16] = UInt8(nv)
} else {
bytes[15] = (bytes[15] & 0xF0) | 0xF8
bytes[16] = 0x00
}
}
}
Now your getter has a possibility of returning nil, and your setter doesn't depend on the existing value.

The error is here:
set {
if (bytes[15] == 8 && bytes[16] == 0) {
return nil // <--- HERE
}
You cannot return anything from set { }. If you want to break, just return instead.
set {
if (bytes[15] == 8 && bytes[16] == 0) {
return
}

Related

How to get arguments of NSRunningApplication?

How do I get the list of arguments using during launch for a NSRunningApplication, similar to the ones I see when I run ps aux:
let workspace = NSWorkspace.shared
let applications = workspace.runningApplications
for application in applications {
// how do I get arguments that were used during application launch?
}
The "ps" tool uses sysctl() with KERN_PROCARGS2 to get the arguments of a running process. The following is an attempt to translate the code from adv_cmds-153/ps/print.c to Swift. That file also contains a documentation of the memory layout of the raw argument space and explains how to locate the string arguments in that memory.
func processArguments(pid: pid_t) -> [String]? {
// Determine space for arguments:
var name : [CInt] = [ CTL_KERN, KERN_PROCARGS2, pid ]
var length: size_t = 0
if sysctl(&name, CUnsignedInt(name.count), nil, &length, nil, 0) == -1 {
return nil
}
// Get raw arguments:
var buffer = [CChar](repeating: 0, count: length)
if sysctl(&name, CUnsignedInt(name.count), &buffer, &length, nil, 0) == -1 {
return nil
}
// There should be at least the space for the argument count:
var argc : CInt = 0
if length < MemoryLayout.size(ofValue: argc) {
return nil
}
var argv: [String] = []
buffer.withUnsafeBufferPointer { bp in
// Get argc:
memcpy(&argc, bp.baseAddress, MemoryLayout.size(ofValue: argc))
var pos = MemoryLayout.size(ofValue: argc)
// Skip the saved exec_path.
while pos < bp.count && bp[pos] != 0 {
pos += 1
}
if pos == bp.count {
return
}
// Skip trailing '\0' characters.
while pos < bp.count && bp[pos] == 0 {
pos += 1
}
if pos == bp.count {
return
}
// Iterate through the '\0'-terminated strings.
for _ in 0..<argc {
let start = bp.baseAddress! + pos
while pos < bp.count && bp[pos] != 0 {
pos += 1
}
if pos == bp.count {
return
}
argv.append(String(cString: start))
pos += 1
}
}
return argv.count == argc ? argv : nil
}
There is only a simple error handling: if anything goes wrong, the function returns nil.
For an instance of NSRunningApplication you can then call
processArguments(pid: application.processIdentifier)

Cannot convert value of type 'Int' to expected argument type 'Bool'

I am new to Swift and can't figure out why I am getting the following error:
exit status 1
main.swift:17:13: error: cannot convert value of type 'Int' to expected argument type 'Bool'
else if remainder2 && remainder == 0{
^~~~~~~~~~
main.swift:21:12: error: cannot convert value of type 'Int' to expected argument type 'Bool'
else if remainder && remainder3 == 0 {
^~~~~~~~~
For the following code:
var aYear = Int(readLine()!)!
func isLeap(year: Int) {
let remainder = year % 4
let remainder2 = year % 400
let remainder3 = year % 100
var whatLeap = false
if remainder == 0 {
whatLeap = true
} else if remainder2 && remainder == 0 {
whatLeap = true
} else if remainder && remainder3 == 0 {
whatLeap = false
} else {
whatLeap = false
}
if whatLeap == true {
print("YES")
} else {
print("NO")
}
}
isLeap(year: aYear)
I have tried changing the variable "whatLeap" to a String, but I get a similar error.
Any help will be greatly appreciated!
You need to state the two statements fully:
remainder2 == 0 && remainder == 0
What you are saying if you leave the statement as is is remainder2 == true && remainder == 0, which would explain why you get the error message Int to Bool.
To give another example:
var tOrF = false
if tOrF == true {} and if tOrF {} are same statements.
You need to compare both variables to 0 otherwise you are saying if remainder2 exists and remainder == 0.
if remainder == 0 {
whatLeap = true
} else if remainder2 == 0 && remainder == 0 {
whatLeap = true
} else if remainder == 0 && remainder3 == 0 {
whatLeap = false
}
I have some improvements to suggest:
Numbered variables are almost always a bad idea. Why should people have to constantly glance up and down between the usages/definitions, to see which one is which one is which, when you can just label them directly? It's particularly aggregious here, when the number variables represent 4, 400, 100, unlike what I presume most people would expect, 4, 100, 400. I would recommend you use descriptive names:
func isLeap(year: Int) {
let remainderMod4 = year % 4
let remainderMod100 = year % 100
let remainderMod400 = year % 400
var isLeapYear = false
if remainderMod4 == 0 {
isLeapYear = true
} else if remainderMod400 == 0 && remainderMod4 == 0 {
isLeapYear = true
} else if remainderMod400 == 0 && remainderMod100 == 0 {
isLeapYear = false
} else {
isLeapYear = false
}
if isLeapYear == true {
print("YES")
} else {
print("NO")
}
}
Don't set temporary values that will be immediately overwritten. Instead, declare the value without initializing it. There is a neat feature of the Swift compiler called "definite initialization", which guarentees that all variables are set at least once before use. Using it earlier than that would cause an error to alert you of the mistake. Because you're never mutating the value, isLeapYear can be promoted to a let constant.
let isLeapYear: Bool
Don't compare a boolean to true. Checking for true is already what if does. That just yields the same boolean. There are some exceptions (e.g. checking if a Bool? is true, not false or nil), but anyway:
if isLeapYear { // ...
Don't use x & y == 0. Use x.isMultiple(of: y) instead, it's much more clear.
let remainderMod4 = year.isMultiple(of: 4)
let remainderMod100 = year.isMultiple(of: 400)
let remainderMod400 = year.isMultiple(of: 400)
At that point, remainderMod4 reads pretty much the same as year.isMultiple(of: 4), so just inline it:
if year.isMultiple(of: 4) == 0 {
isLeapYear = true
} else if year.isMultiple(of: 400) == 0 && year.isMultiple(of: 4) == 0 {
isLeapYear = true
} else if year.isMultiple(of: 400) == 0 && year.isMultiple(of: 100) == 0 {
isLeapYear = false
} else {
isLeapYear = false
}
You can remove your complex if/else branch by using a simpler boolean expression:
let isLeapYear = (year.isMultiple(of: 4) && !year.isMultiple(of: 100))
|| year.isMultiple(of: 400)
You leap-year calculation should only do one thing: figure out if a given year is a leap year. It would be inappropriate for its job to also print out the result to a user. Do that in a separate function, or for a one-off like this, in the global "script area":
func isLeap(year: Int) -> Bool {
return (year.isMultiple(of: 4) && !year.isMultiple(of: 100))
|| year.isMultiple(of: 400)
}
let aYear = Int(readLine()!)!
if isLeap(year: aYear) {
print("YES")
} else {
print("NO")
}

Practical number algorithm too slow

I am trying to write a program to find the practical numbers, from an input from 1 to n.
Practical numbers : https://en.wikipedia.org/wiki/Practical_number
My code is running correctly but it is extremely slow - takes over 20 minutes when it should take 10 seconds. This happens when calculating numbers around 50 - it gets stuck at 44.
It is written in Swift
import Foundation
func getInteger() -> Int {
var firstNum:Int = 0
while true {
// get value from user. Using optional input since readLine returns an optional string.
let input = readLine()
// ensure string is not nil
if let unwrappedInput = input {
if let unwrappedInt = Int(unwrappedInput) {
firstNum = unwrappedInt
break
}
else { // the input doesn't convert into an int
print("`\(unwrappedInput)` is not an integer. Please enter an integer")
}
}
else { // did not enter anything
print("Please enter an integer")
}
}
return firstNum
}
func addOne(signArray: [Int]) -> [Int] { // finds the combinations
var signArray2 = [Int]()
for i in 0...signArray.count-1 {
signArray2.append (signArray[i])
}
for i in 0...signArray2.count-1 {
if signArray2[i] == 1 {
signArray2[i] = 0
}
else {
signArray2[i] = 1
break
}
}
return signArray2
}
func signEval (signArray: [Int], divArray: [Int], inNum: Int) -> Bool {// changes 2nd
var counts = 0
for i in 0...divArray.count-1 {
if signArray[i] == 0 {
counts = divArray[i] + counts }
if counts == inNum {
return true
}
}
return false
}
print("Please enter a number to find the summable numbers up to that number:")
var input2 = getInteger()// if num = 1 print 1 if num = 2 print 1 and 2 else print >2 1, 2
var inNum = 0
var numHalf = 0.0
var numRound = 0.0
var numCheck = false
var numCheck2 = false
var numQuarter = 0.0
var numSixth = 0.0
var divArray:[Int] = []
var theirArray = [Int]()
var signArray = [Int]()// array of 0s and 1s
var summableArray:[Int] = [1,2] // need to check if num is bigger than 2!
for input in 1...input2 {
numHalf = Double (input) / 2.0
numRound = round(numHalf)
if numRound == numHalf {
numCheck = true }
if input > 2 && numCheck == false { // odd numbers greater than one are not summable
}
else { // these are possible summable nums
numQuarter = Double (input) / 4.0
numRound = round(numQuarter)
if numRound == numQuarter {
numCheck = true
}
else {
numCheck = false
}
numSixth = Double(input) / 6.0
numRound = round(numSixth)
if numRound == numSixth {
numCheck2 = true }
else { numCheck2 = false}
if numCheck == true || numCheck2 == true {
theirArray = []
divArray = []
signArray = []
summableArray = []
for i in 1...input {
theirArray.append (i)
}
for i in 1...input { // creates an array of all the diviors of inputted number
if input%i == 0 {
divArray.append (i)
}
}
for j in 1...divArray.count {//
signArray.append(0)
}
for i in 1...input{
let x: Int = Int(pow(Double(2),Double(input-1)))// int 2 to the power of input -1
var Boolcheck = false
for q in 1...x-1 { // i to 2^n -1 (sequence to check)
Boolcheck = (signEval(signArray: signArray, divArray: divArray, inNum: i))// checks
signArray = addOne(signArray: signArray)// adding the ones to the array
if Boolcheck == true {
summableArray.append(i)// creates array of mini summable numbers
break
}
}
if summableArray.count == input {
print ("\(input)")
}
}
}
}
}

Swift 3 conversion - 'predecessor()' is unavailable

I am getting the above error. So how do we convert the following codes to swift 3 compatible?
let charactersAreInCorrectState = { () -> Bool in
let previousContext = self.textDocumentProxy.documentContextBeforeInput
if previousContext == nil || (previousContext!).characters.count < 3 {
return false
}
var index = previousContext!.endIndex
index = index.predecessor()
if previousContext![index] != " " {
return false
}

UnicodeScalar string has no value property in swift 3.0

In swift 2.0 i had written below function that was working fine.
private func escape(string: String) -> String {
let unicode = string.unicodeScalars
var newString = ""
for i in unicode.startIndex ..< unicode.endIndex {
let char = unicode[i]
if char.value < 9 || (char.value > 9 && char.value < 32) // < 32 == special characters in ASCII, 9 == horizontal tab in ASCII
|| char.value == 39 { // 39 == ' in ASCII
let escaped = char.escape(asASCII: true)
newString.appendContentsOf(escaped)
} else {
newString.append(char)
}
}
return newString
}
But after update to Xcode 8 and Swift 3.0 my code has error that unicodeScalars has no property .value to access unicode value of a character. So what is the new property for the same in Swift3.0?
Something like this may be?
private func escape(string : String) -> String {
var newString = ""
string.unicodeScalars.forEach { char in
let expression = (char.value > 9 && char.value < 32)
(char.value < 9) || expression || (char.value == 39) ? newString.append(char.escaped(asASCII: true)) : newString.append(String(char))
}
return newString
}