Swift 3 Custom Extension of Ns Measurement? Ex. Sheeps to Goats

Swift 3 Custom extension of ns measurement? Ex. Sheeps to goats

See https://developer.apple.com/reference/foundation/nsdimension

Example implementation:

class Animal : Dimension {
static let sheep = Animal(symbol: "Sh", converter: UnitConverterLinear(coefficient: 2.0))
static let goat = Animal(symbol: "Go", converter: UnitConverterLinear(coefficient: 1.0))
static let elephant = Animal(symbol: "El", converter: UnitConverterLinear(coefficient: 100.0))

override class func baseUnit() -> Animal {
return Animal.goat
}
}

var x = Measurement(value:5, unit: Animal.sheep) // 5.0 Sh
x.convert(to: Animal.goat) // 10.0 Go
x.convert(to: Animal.elephant) // 0.1 El

How to format a Swift 3 nsmeasurement string to at most 2 decimal places after conversion?

By using a MeasurementFormatter:

var x = Measurement(value:19, unit: UnitMass.kilograms)
x.convert(to:UnitMass.pounds)
x.description // 41.8878639834918 lb

let m = MeasurementFormatter()
m.numberFormatter.maximumFractionDigits = 2
m.string(from: x) // 41.89 lb

Date Format in Swift

You have to declare 2 different NSDateFormatters, the first to convert the string to a NSDate and the second to print the date in your format.

Try this code:

let dateFormatterGet = NSDateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"

let dateFormatterPrint = NSDateFormatter()
dateFormatterPrint.dateFormat = "MMM dd,yyyy"

let date: NSDate? = dateFormatterGet.dateFromString("2016-02-29 12:24:26")
print(dateFormatterPrint.stringFromDate(date!))

Swift 3 and higher:

From Swift 3 NSDate class has been changed to Date and NSDateFormatter to DateFormatter.

let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"

let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "MMM dd,yyyy"

if let date = dateFormatterGet.date(from: "2016-02-29 12:24:26") {
print(dateFormatterPrint.string(from: date))
} else {
print("There was an error decoding the string")
}

conversion from NSTimeInterval to hour,minutes,seconds,milliseconds in swift

Swift supports remainder calculations on floating-point numbers, so we can use % 1.

var ms = Int((interval % 1) * 1000)

as in:

func stringFromTimeInterval(interval: TimeInterval) -> NSString {

let ti = NSInteger(interval)

let ms = Int((interval % 1) * 1000)

let seconds = ti % 60
let minutes = (ti / 60) % 60
let hours = (ti / 3600)

return NSString(format: "%0.2d:%0.2d:%0.2d.%0.3d",hours,minutes,seconds,ms)
}

result:

stringFromTimeInterval(12345.67)                   "03:25:45.670"

Swift 4:

extension TimeInterval{

func stringFromTimeInterval() -> String {

let time = NSInteger(self)

let ms = Int((self.truncatingRemainder(dividingBy: 1)) * 1000)
let seconds = time % 60
let minutes = (time / 60) % 60
let hours = (time / 3600)

return String(format: "%0.2d:%0.2d:%0.2d.%0.3d",hours,minutes,seconds,ms)

}
}

Use:

self.timeLabel.text = player.duration.stringFromTimeInterval()

Get file size in Swift

Use attributesOfItemAtPath instead of attributesOfFileSystemForPath
+ call .fileSize() on your attr.

var filePath: NSString = "your path here"
var fileSize : UInt64
var attr:NSDictionary? = NSFileManager.defaultManager().attributesOfItemAtPath(filePath, error: nil)
if let _attr = attr {
fileSize = _attr.fileSize();
}

In Swift 2.0, we use do try catch pattern, like this:

let filePath = "your path here"
var fileSize : UInt64 = 0

do {
let attr : NSDictionary? = try NSFileManager.defaultManager().attributesOfItemAtPath(filePath)

if let _attr = attr {
fileSize = _attr.fileSize();
}
} catch {
print("Error: \(error)")
}

In Swift 3.x/4.0:

let filePath = "your path here"
var fileSize : UInt64

do {
//return [FileAttributeKey : Any]
let attr = try FileManager.default.attributesOfItem(atPath: filePath)
fileSize = attr[FileAttributeKey.size] as! UInt64

//if you convert to NSDictionary, you can get file size old way as well.
let dict = attr as NSDictionary
fileSize = dict.fileSize()
} catch {
print("Error: \(error)")
}

NSRange from Swift Range?

Swift String ranges and NSString ranges are not "compatible".
For example, an emoji like counts as one Swift character, but as two NSString
characters (a so-called UTF-16 surrogate pair).

Therefore your suggested solution will produce unexpected results if the string
contains such characters. Example:

let text = "Long paragraph saying!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
let start = distance(text.startIndex, substringRange.startIndex)
let length = distance(substringRange.startIndex, substringRange.endIndex)
let range = NSMakeRange(start, length)

if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: range)
}
})
println(attributedString)

Output:


Long paragra{
}ph say{
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}ing!{
}

As you see, "ph say" has been marked with the attribute, not "saying".

Since NS(Mutable)AttributedString ultimately requires an NSString and an NSRange, it is actually
better to convert the given string to NSString first. Then the substringRange
is an NSRange and you don't have to convert the ranges anymore:

let text = "Long paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: nsText)

nsText.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in

if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
}
})
println(attributedString)

Output:


Long paragraph {
}saying{
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}!{
}

Update for Swift 2:

let text = "Long paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: text)

nsText.enumerateSubstringsInRange(textRange, options: .ByWords, usingBlock: {
(substring, substringRange, _, _) in

if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
}
})
print(attributedString)

Update for Swift 3:

let text = "Long paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: text)

nsText.enumerateSubstrings(in: textRange, options: .byWords, using: {
(substring, substringRange, _, _) in

if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.red, range: substringRange)
}
})
print(attributedString)

Update for Swift 4:

As of Swift 4 (Xcode 9), the Swift standard library
provides method to convert between Range<String.Index> and NSRange.
Converting to NSString is no longer necessary:

let text = "Long paragraph saying!"
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstrings(in: text.startIndex..<text.endIndex, options: .byWords) {
(substring, substringRange, _, _) in
if substring == "saying" {
attributedString.addAttribute(.foregroundColor, value: NSColor.red,
range: NSRange(substringRange, in: text))
}
}
print(attributedString)

Here substringRange is a Range<String.Index>, and that is converted to the
corresponding NSRange with

NSRange(substringRange, in: text)

What's NSLocalizedString equivalent in Swift?

The NSLocalizedString exists also in the Swift's world.

func NSLocalizedString(
key: String,
tableName: String? = default,
bundle: NSBundle = default,
value: String = default,
#comment: String) -> String

The tableName, bundle, and value parameters are marked with a default keyword which means we can omit these parameters while calling the function. In this case, their default values will be used.

This leads to a conclusion that the method call can be simplified to:

NSLocalizedString("key", comment: "comment")

Swift 5 - no change, still works like that.

Convert UIImage to NSData and convert back to UIImage in Swift?

UIImage(data:imageData,scale:1.0) presuming the image's scale is 1.

In swift 4.2, use below code for get Data().

image.pngData()


Related Topics



Leave a reply



Submit