How to resolve 'scanLocation' was deprecated in iOS 13.0 - swift

When trying to use a Scanner I am getting the warning that 'scanLocation' was deprecated in iOS 13.0. Since being able to scan from the next location is rather fundamental to scanning a String, wondering what to use instead of scanLocation. Apple's documentation for Scanner does not even mention the deprecation, let alone suggest what has taken the place of scanLocation.
Example of using scanLocation, which is deprecated:
while !scanner.isAtEnd {
print(scanner.scanUpToCharacters(from: brackets))
let block = scanner.string[scanner.currentIndex...]
print(block)
scanner.scanLocation = scanner.scanLocation + 1
}

tl;dr - use currentIndex instead of scanLocation when using Scanner in Swift.
Shame on Apple for the poor documentation. But based on information in the NSScanner.h file for the Objective-C version of Scanner, only in Swift, the scanLocation property has been deprecated and replaced with the currentIndex property.

#rmaddy already gave the correct answer, but this shows how to increment the currentIndex since it is different from just adding 1 to the scanLocation.
while !scanner.isAtEnd {
print(scanner.scanUpToCharacters(from: brackets))
let block = scanner.string[scanner.currentIndex...]
print(block)
scanner.currentIndex = scanner.string.index(after: scanner.currentIndex)
}

Related

Detecting if Mac has a backlit keyboard

It’s quite easy to detect if Mac has an illuminated keyboard with ioreg at the command line:
ioreg -c IOResources -d 3 | grep '"KeyboardBacklight" =' | sed 's/^.*= //g'
But how can I programmatically get this IOKit boolean property using the latest Swift? I’m looking for some sample code.
I figured out the following with some trial and error:
Get the "IOResources" node from the IO registry.
Get the "KeyboardBacklight" property from that node.
(Conditionally) convert the property value to a boolean.
I have tested this on an MacBook Air (with keyboard backlight) and on an iMac (without keyboard backlight), and it produced the correct result in both cases.
import Foundation
import IOKit
func keyboardHasBacklight() -> Bool {
let port: mach_port_t
if #available(macOS 12.0, *) {
port = kIOMainPortDefault // New name as of macOS 12
} else {
port = kIOMasterPortDefault // Old name up to macOS 11
}
let service = IOServiceGetMatchingService(port, IOServiceMatching(kIOResourcesClass))
guard service != IO_OBJECT_NULL else {
// Could not read IO registry node. You have to decide whether
// to treat this as a fatal error or not.
return false
}
guard let cfProp = IORegistryEntryCreateCFProperty(service, "KeyboardBacklight" as CFString,
kCFAllocatorDefault, 0)?.takeRetainedValue(),
let hasBacklight = cfProp as? Bool
else {
// "KeyboardBacklight" property not present, or not a boolean.
// This happens on Macs without keyboard backlight.
return false
}
// Successfully read boolean "KeyboardBacklight" property:
return hasBacklight
}
As an addendum to Martin’s excellent answer, here are the notes I got from Apple’s Developer Technical Support:
Calling I/O Kit from Swift is somewhat challenging. You have
two strategies here:
You can wrap the I/O Kit API in a Swift-friendly wrapper and then use that to accomplish your task.
You can just go straight to your task, resulting in lots of ugly low-level Swift.
Pulling random properties out of the I/O Registry is not the best path
to long-term binary compatibility. Our general policy here is that we
only support properties that have symbolic constants defined in the
headers (most notably IOKitKeys.h, but there are a bunch of others).
KeyboardBacklight has no symbolic constant and thus isn’t supported.
Make sure you code defensively. This property might go away, change
meaning, change its type, and so on. Your code must behave reasonable
in all such scenarios.
Please make sure you file an enhancement request for a proper API to
get this info, making sure to include a high-level description of your
overall goal.

How to correctly add a spinner on macOS Catalina as Style.spinning is deprecated?

I always create a spinner with NSProgressIndicator like this
let spinner = NSProgressIndicator()
spinner.style = .spinning
It works fine, but I recently found the
NSProgressIndicator.Style.spinning is deprecated. I have went searched around, but did not quite find out what is the recommended way right now to create a spinner on macOS. Can anyone please help here?
Thank you
It looks like an error in the documentation. In macOS 10.15 NSProgressIndicatorBarStyle and NSProgressIndicatorSpinningStyle are deprecated. Somehow NSProgressIndicatorStyleBar and NSProgressIndicatorStyleSpinning, .bar and .spinning in Swift, were also deprecated in the documentation but they aren't in NSProgressIndicator.h.
typedef NS_ENUM(NSUInteger, NSProgressIndicatorStyle) {
NSProgressIndicatorStyleBar = 0,
NSProgressIndicatorStyleSpinning = 1
};
and
/* Please instead use the more modern versions of these constants.
*/
static const NSProgressIndicatorStyle NSProgressIndicatorBarStyle API_DEPRECATED_WITH_REPLACEMENT("NSProgressIndicatorStyleBar", macos(10.2,10.14)) = NSProgressIndicatorStyleBar;
static const NSProgressIndicatorStyle NSProgressIndicatorSpinningStyle API_DEPRECATED_WITH_REPLACEMENT("NSProgressIndicatorStyleSpinning", macos(10.2,10.14)) = NSProgressIndicatorStyleSpinning;
The style isn't deprecated; they've just been making the names consistent so it's easier to turn them into Swift.

Scripting Bridge classes with Swift 3

I am trying to instantiate a SB class using Swift but it doesn't seem to work:
if let messageClass = (mail as! SBApplication).class(forScriptingClass:"outgoing message") {
let message = (messageClass as! SBObject.Type).init(properties: ["subject": "message subjects"]) as MailOutgoingMessage
mail.outgoingMessages!().add(message)
print("Subject: \(message.subject)")
print("Outgoing messages: \(mail.outgoingMessages!().count)")
}
All I get in the output is:
Subject: nil
Outgoing messages: 0
I know that I should cast the message to a MailOutgoingMessage.type and not SBObject.type but I couldn't access the init method otherwise.
Someone has experience using Scripting Bridge with Swift? Clues?
Scripting Bridge is nasty, obfuscated and broken. If you have to use SB, Tony Ingraldi wrote some helper tools for Swift users. TBH, I recommend using AppleScript-ObjC over SB simply because AppleScript at least works.
For a native Swift-AE bridge, see SwiftAutomation. I'm still working on the documentation, but the code itself descends from appscript which is the only AppleScript alternative of the last 20 years that actually works right, so is just about beta-quality now.
Swift (and AppleScript) users who'd like to see Apple adopt SwiftAutomation in 10.3 are strongly encouraged to submit duplicate Radar tickets to bugreport.apple.com requesting it, e.g. here's one already copied to OpenRadar if you want to copy-paste it as-is (include the original rdar:// to help the Radar team resolve it quicker): openradar.appspot.com/29332915

Xcode 8 random command failed due to signal segmentation fault 11

I have a strange problem with the new Xcode 8 (no beta version) and swift3.
Once every other 3-4 times that I compile my code I get a 'command failed due to signal segmentation fault 11' error. I just need to enter new empty line, or sometimes changing some spaces, or add a comment (everywhere in the code) and the error disappears and I can compile again.
This is really strange because I'm not changing anything in the code! And sometimes I can compile and it works, then I don't change anything, I compile again and I get the error.
This is really annoying!
I have noticed this is happening since I have installed several 'Firebase' pods (Firebase, Firebase/Auth etc...). But I need them.
Anyone has any suggestion?
PS: I have set the Enable Bitcode of my project to No as many solution suggested, but nothing. In the error message it is not indicated any swift page where the error can be, an example is:
While loading members for 'Class_name' at
While deserializing 'func_name' (FuncDecl #42)
'func_name' is this one:
public class func loginUser(fir_user: FIRUser) {
let user = SFUser()
user.email = fir_user.email
user.isLogged = true
try! sfRealm.write() {
sfRealm.add(user, update:true)
}
var userToAdd = [String:AnyObject]()
userToAdd["email"] = fir_user.email! as NSString
let ref=FIRDatabase.database().reference()
let usersRef = ref.child(childName)
usersRef.setValue([key:value])
}
But then, as I said, I can just enter an empty row in another file and it compiles!
Thanks
I have the same issue i just figure out that i was using xcode 8.1 and the project's working copy was in xcode 8.2.1 so i just re install xcode 8.2.1 and problem got solved. Hope other can get the help trough this.
Ok, it seems that I have found the solution: it is a problem with Firebase and cocoapods, so 2 solutions:
Download Firebase and import into your project
I, instead, updated cocoapods to the last version and it worked. Upgraded Firebase - Now Getting Swift Compile Error
In my case there was some type checking issue deep down the compiler so the editor didn't give error in the gutter but on building the project I was getting signal setmentation fault 11 error:
1. While type-checking 'GetStoreAPIRequestModel' at /Users/.../StoreAPIModel.swift:9:1
2. While type-checking expression at [/Users/.../StoreAPIModel.swift:15:18 - line:15:31] RangeText="[Dictionary]()"
3. While resolving type [Dictionary] at [/Users/.../StoreAPIModel.swift:15:18 - line:15:29] RangeText="[Dictionary]"
So I changed my code from:
var stores = [Dictionary]() {
willSet {
allStores.removeAll()
for model in newValue {
allStores.append(StoreAPIModel(dictionary: model as! Dictionary).getModel())
}
}
}
To (more descriptive dictionary):
var stores = [[String : Any]]() {
willSet {
allStores.removeAll()
for model in newValue {
allStores.append(StoreAPIModel(dictionary: model as [String : AnyObject]).getModel())
}
}
}
This is tricky problem. Issue can be with line of code or syntax. I was getting similar error and it was due to incorrect usage of dictionary. I was trying to increment the value of dictionary element.
Solution is to triage the code, detailed error provide which module has issue, so try commenting part of code until you find the line which is causing the issue.
Hi i had the same issue with FireBase , my problem was that i was extending FIRStorageReference and FIRDatabaseReference and some time it compile successfully some time i get
command failed due to signal segmentation fault 11
so i removed that files and implement the method other way , now everything works fine.
Found my problem when this occurred. (No cocoapods.) I thought I had left the program in a working state, but I was wrong. I am writing a straightforward command-line program. What it does is somewhat general, so I defined all the strings that make it specific in let statements at the top of the program so that I could someday use the program in a different context.
Since that was working so well, I thought I'd be clever and do the same with a filter of an array of dictionaries. I turned:
list.filter { $0["SearchStrings"] == nil }
into:
let test = { $0["SearchStrings"] == nil }
// ...
list.filter(test)
meaning to continue working on the let, but I never went back and did that. Building gave me the segmentation fault error. Defining test as a function fixed the problem.
(Incidentally, I understand how to strip a filtering function down to the terse braces notation in the context of the call to Array.filter, and why that works, but I don't understand why I can't assign the brace expression to a constant and use it as such.)

Check function exists - Lazy Symbol Binding Failed

I'm using a method CGPathGetPathBoundingBox that is only available in iOS 4.0. I'm doing a check against NULL to see if it is available as suggested in Apple Docs but I'm getting the following runtime error:
dyld: lazy symbol binding failed: Symbol not found: _CGPathGetPathBoundingBox
Referenced from: /Users/..
Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.2.sdk/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
I set the Core Graphics framkework to type "weak", but to no affect. Same things happens on real device. When I step through in the debugger the if statement is always executed.
if (CGPathGetPathBoundingBox != NULL) {
self.smallBounds = CGPathGetPathBoundingBox(tempPath);
}
else {
self.smallBounds = CGPathGetBoundingBox(tempPath);
}
I got this answer after posting to the Apple Dev Forum, it seems to be a bug:
CGPath.h says
CG_EXTERN CGRect CGPathGetPathBoundingBox(CGPathRef path) CG_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
But the docs say it's a 4.0 function. I believe that's the problem.
I would file a bug.
I'm not sure what the right workaround is because since the function isn't properly being weak linked your app will crash on an OS without the function.
Maybe you need to use respondsToSelector instead?