Swift 3 Local Notifications - Setting Automatic Timezone - uilocalnotification

So this worked flawlessly in Swift 2 but in Swift 3 it has problems:
func myNotifications () {
let interval = 2.0
var daysOut = 2.0
let myArray =getArray()
for i in 0..<myArray.count {
let message = ("\(myArray[i])\n-\(myArray[i])")
let localNotification = UILocalNotification()
localNotification.fireDate = Date(timeIntervalSinceNow: (60*60*24*daysOut))
localNotification.alertBody = message
localNotification.timeZone = NSTimeZone.autoupdatingCurrent
localNotification.category = "Message"
UIApplication.shared.scheduleLocalNotification(localNotification)
daysOut += interval
}
let arrayCount = Double(myArray.count)
let lastNotif_Date = Date(timeIntervalSinceNow: (60*60*24*interval*(quoteCount+1)))
userPref_NSDefault.set(lastNotif_Date, forKey: "notification_EndDate")
}
Specifically, this line no longer works which is a big deal because I have users in multiple timezones and I want to make sure this works:
localNotification.timeZone = NSTimeZone.autoupdatingCurrent
I get the error message:
Type "NSTimeZone" has no member "autoUpdatingCurrent"
Any ideas? I tried "timeZone.automatic", ".automatic", and some other variations but haven't been able to figure it out.

autoupdatingCurrent != autoupdatingCurrent
NSTimeZone has been renamed to TimeZone

Related

Heartrate with no decimal places

Im doing a watch app for the Apple Watch in Xcode and the sample code from the Apple Developer site SpeedySloth: Creating a Workout has the HeartRate rounded to one decimal place, e.g. 61.0
How can I fix this?
case HKQuantityType.quantityType(forIdentifier: .heartRate):
/// - Tag: SetLabel
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
let value = statistics.mostRecentQuantity()?.doubleValue(for: heartRateUnit)
let roundedValue = Double( round( 1 * value! ) / 1 )
label.setText("\(roundedValue) BPM")
I tried changing both the 1's in there to 0 but that gave me a 6.1 BPM or a 0.0 BPM
Thanks
A simple solution is to round to an integer and show the integer.
let value = // ... some Double ...
let s = String(Int(value.rounded(.toNearestOrAwayFromZero)))
label.setText(s + " BPM")
Properly, however, you should put formatting a string based on a number into the hands of a NumberFormatter. That's its job: to format a number.
let i = value.rounded(.toNearestOrAwayFromZero)
let nf = NumberFormatter()
nf.numberStyle = .none
let s = nf.string(from: i as NSNumber)!
// ... and now show the string

Can DateComponentsFormatter format fractional seconds?

I want to print, e.g., the value 1.5 as "1.5 sec", like Safari's timeline does, and I'm trying to use DateComponentsFormatter for it.
Unfortunately, its .allowedUnits only goes down to .second (even though the enum has .nanosecond). I tried setting .allowsFractionalUnits = true, but I'm still getting "0 sec".
Is there any way to get fractional seconds out of DateComponentsFormatter?
For positional units style, DateComponentsFormatter can be used together with NumberFormatter to get locale-aware string.
func format(_ seconds: TimeInterval) -> String {
let components = DateComponentsFormatter()
components.allowedUnits = [.minute, .second]
components.allowsFractionalUnits = true // does not work as expected
components.unitsStyle = .positional
components.zeroFormattingBehavior = .pad
let fraction = NumberFormatter()
fraction.maximumIntegerDigits = 0
fraction.minimumFractionDigits = 0
fraction.maximumFractionDigits = 3
fraction.alwaysShowsDecimalSeparator = false
let fractionalPart = NSNumber(value: seconds.truncatingRemainder(dividingBy: 1))
return components.string(from: seconds)! + fraction.string(from: fractionalPart)!
}
print(Locale.current) // ru_RU (current)
print(format(600.5)) // 10:00,5 <- note locale specific decimal separator
Unfortunately, using this method for other date styles is even more hacky.

How do you set previewLayer.connection.videoOrientation in Swift 2?

In Objective-C you can do this:
if ( UIDeviceOrientationIsPortrait( deviceOrientation ) || UIDeviceOrientationIsLandscape( deviceOrientation ) ) {
AVCaptureVideoPreviewLayer *previewLayer = (AVCaptureVideoPreviewLayer *)self.previewView.layer;
previewLayer.connection.videoOrientation = (AVCaptureVideoOrientation)deviceOrientation;
}
But in Swift, what's the best way to translate this last line? You can't do "deviceOrientation as AVCaptureVideoOrientation".
Best I could come up with so far is:
if(UIDeviceOrientationIsPortrait(deviceOrientation) || UIDeviceOrientationIsLandscape(deviceOrientation)) {
let myPreviewLayer: AVCaptureVideoPreviewLayer = self.previewLayer
myPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientation.init(rawValue: deviceOrientation.rawValue-1)!
}
But this seems inelegant. The -1 is there because it's just an enum at the end of the day, and the UIDeviceOrientation enum has an "Unknown" one at position 0 that the AVCaptureVideoOrientation does not have...
This does a great job on swift 4:
previewLayer.connection?.videoOrientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!
try this
let avLayer = (self.previewView.layer as AVCaptureVideoPreviewLayer)
let connection = avLayer.connection
let orientation = AVCaptureVideoOrientation(rawValue: self.interfaceOrientation.rawValue)!
connection.videoOrientation = orientation
This is the conversion I got:
if UIDeviceOrientationIsPortrait(deviceOrientation) || UIDeviceOrientationIsLandscape(deviceOrientation) {
var previewLayer: AVCaptureVideoPreviewLayer = previewView.layer
previewLayer.connection.videoOrientation = deviceOrientation
}
The converter I used tends to not know what the code is supposed to look like some times (Int vs. CGFloat) so it might not work without de-bugging. let me know if it does what you want, for example, the variable could probably be changed to a constant.
connection.videoOrientation = AVCaptureVideoOrientation.Portrait
You can find the constants AVCaptureVideoOrientation values in swift header files. (Swift 2)

XCode 7 beta 2 String is not convertible to StringLiteralConvertible

I was doing a playground to check swift 2.0 and this happens:
I do not know if im missing something, or is this normal or what? Thanks.
In swift 1.2 is working as expected XCode 6.3.
EDIT: Code
//: Playground - noun: a place where people can play
import Foundation
var str = "Hello, playground"
let languageType: String = "Swift"
var version = 1.0 //infered
let introduced = 2014 //infered
let isAwesome = true //infered
let π = 3.1415927
let 🐶🐮 = "dogcow"
let someString = "I appear to be a string"
let pathComponent = "~/Documents/Swift".pathComponents
var s = String("bla vla nla")
for character in "catDog" {
print(character)
}
the API for String has changed in Swift 2, to accomplish what it looks like you are trying to do, you would instead use for character in "catDog".characters {...}
an excellent reference is Nate Cook's swiftdoc.org

Spritekit Swift particle SKEmitterNode add remove

so this is nice for create a particle, but whats the right way to remove it , after the duration, sparkEmmiter.particleLifetime do not remove it automatically
let sparkEmmiter = SKEmitterNode(fileNamed: "MyParticle.sks")
sparkEmmiter.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2 - 200)
sparkEmmiter.name = "sparkEmmitter"
sparkEmmiter.zPosition = 1
sparkEmmiter.targetNode = self
sparkEmmiter.particleLifetime = 1
self.addChild(sparkEmmiter)
this solutions produce simulator crash
var re = SKAction.waitForDuration(1)
var remove = SKAction.removeFromParent()
var seq = SKAction.sequence([re , remove])
sparkEmmiter.runAction(seq)

Resources