Swift 2.0 : 'enumerate' is unavailable: call the 'enumerate()' method on the sequence
Many global functions have been replaced by protocol extension methods,
a new feature of Swift 2, so enumerate()
is now an extension method
for SequenceType
:
extension SequenceType {
func enumerate() -> EnumerateSequence<Self>
}
and used as
let mySwiftStringArray = [ "foo", "bar" ]
for (index, string) in mySwiftStringArray.enumerate() {
print(string)
}
And String
does no longer conform to SequenceType
, you have to
use the characters
property to get the collection of Unicode
characters. Also, count()
is a protocol extension method of CollectionType
instead of a global function:
let myString = "foo"
let stringLength = myString.characters.count
print(stringLength)
Update for Swift 3: enumerate()
has been renamed to enumerated()
:
let mySwiftStringArray = [ "foo", "bar" ]
for (index, string) in mySwiftStringArray.enumerated() {
print(string)
}
enumerate is unavailable call the enumerate method on the sequence
In Swift 2, enumerate
is not a global function anymore, it's an extension of SequenceType
.
Call it directly on the sequence to enumerate like this:
for (index, key) in row.enumerate() {
// ...
}
Error when using reduce() in Swift 2.0
You fix this the same way that you fixed your problem with enumerate()
. In Swift 2, reduce has been removed as a global function and has been added as an instance method on all objects that conform to the SequenceType
protocol via a protocol extension. Usage is as follows.
var hashValue: Int {
return blocks.reduce(0) { $0.hashValue ^ $1.hashValue }
}
How to resolve: 'keyWindow' was deprecated in iOS 13.0
This is my solution:
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.compactMap({$0 as? UIWindowScene})
.first?.windows
.filter({$0.isKeyWindow}).first
Usage e.g.:
keyWindow?.endEditing(true)
AVAudioSession setCategory availability in Swift 4.2
iOS 10+
If you are targeting iOS 10+, just transition to the new API and use:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
Older iOS versions
When you try this for an app targeting an older iOS version (for example iOS 9) you will get an setCategory(_:mode:options:)' is only available on iOS 10.0 or newer
Error.
This has been reported as an error in Apple's API and fixed in Xcode 10.2. For older Xcode versions (for example Xcode 10.1) there is a workaround I found. When you create an Objective-C helper as described you can still access the old API because it is still exposed for Objective-C.
Workaround 1: .perform() Method
If you want a quick inline fix without the error handling, you can call the Obj.-C API with the .perform()
method:
if #available(iOS 10.0, *) {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
} else {
// Set category with options (iOS 9+) setCategory(_:options:)
AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:withOptions:error:"), with: AVAudioSession.Category.playback, with: [])
// Set category without options (<= iOS 9) setCategory(_:)
AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:error:"), with: AVAudioSession.Category.playback)
}
Workaround 2: Helper class method
Here are the steps how to do it right now if you want some more control over errors
- Create a new
Objective-C
file in my caseAudioSessionHelper.m
. When prompted if a Bridging Header File should be created, click Yes (If you don't already have one in your project) - Create a new
Header
fileAudioSessionHelper.h
- Insert Code
#ifndef AudioSessionHelper_h
#define AudioSessionHelper_h
#import <AVFoundation/AVFoundation.h>
@interface AudioSessionHelper: NSObject
+ (BOOL) setAudioSessionWithError:(NSError **) error;
@end
#endif /* AudioSessionHelper_h */
AudioSessionHelper.m#import "AudioSessionHelper.h"
#import <Foundation/Foundation.h>
@implementation AudioSessionHelper: NSObject
+ (BOOL) setAudioSessionWithError:(NSError **) error {
BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:error];
if (!success && error) {
return false;
} else {
return true;
}
}
@end
- Insert your helper class into Bridging Header File
#import "AudioSessionHelper.h"
- Use it in your Swift project
if #available(iOS 10.0, *) {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
} else {
try AudioSessionHelper.setAudioSession()
}
This is a not beautiful and adds lots of unnecessary code and files to your project, so use it if you urgently want or must use Swift 4.2 on Xcode 10.1 right now. In all other cases you would be better off using Xcode 10.2.
How to enumerate an enum with String type?
Swift 4.2+
Starting with Swift 4.2 (with Xcode 10), just add protocol conformance to CaseIterable
to benefit from allCases
. To add this protocol conformance, you simply need to write somewhere:
extension Suit: CaseIterable {}
If the enum is your own, you may specify the conformance directly in the declaration:
enum Suit: String, CaseIterable { case spades = "♠"; case hearts = "♥"; case diamonds = "♦"; case clubs = "♣" }
Then the following code will print all possible values:
Suit.allCases.forEach {
print($0.rawValue)
}
Compatibility with earlier Swift versions (3.x and 4.x)
If you need to support Swift 3.x or 4.0, you may mimic the Swift 4.2 implementation by adding the following code:
#if !swift(>=4.2)
public protocol CaseIterable {
associatedtype AllCases: Collection where AllCases.Element == Self
static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
static var allCases: [Self] {
return [Self](AnySequence { () -> AnyIterator<Self> in
var raw = 0
var first: Self?
return AnyIterator {
let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
if raw == 0 {
first = current
} else if current == first {
return nil
}
raw += 1
return current
}
})
}
}
#endif
Related Topics
Providing a Default Value For an Optional in Swift
How to Atomically Increment a Variable in Swift
Knowing Where Retain Cycles Are and Removing Them
Extensions in My Own Custom Class
Convert a Date (Absolute Time) to Be Sent/Received Across the Network as Data in Swift
Wrong Specialized Generic Function Gets Called in Swift 3 from an Indirect Call
How to Return an Object That I Create in My Data Service Class Through Firebase
How to Set Up Scenekit Collision Detection
How to Easily Duplicate/Copy an Existing Realm Object
Why Is Equatable Not Defined For Optional Arrays
Swift: How to Add a Protocol Extension to a Protocol
Swift - Extra Argument in Call
How to Multiply Two Arrays Element-Wise
How to Parse Json With Decodable Protocol When Property Types Might Change from Int to String
Does Swift Copy on Write For All Structs
How to Make a Weak Protocol Reference in 'Pure' Swift (Without @Objc)