Is there any difference between the debug and release build in terms of code / dependancies?
I recently started using test flight (this uses release builds) and have had nothing but crashes. It works perfectly when I build for debug.
Anyone had this problem?
At the moment I get a exc_breakpoint when the app hits "return true"
Which seems very weird. There is nothing to go wrong when all you have to do is return "true"
import UIKit
import CoreLocation
func calculateRelevance (album: AlbumLight , currentLocation: CLLocation, currentCity: String) -> Bool {
let fromLocationLa: CLLocationDegrees = CLLocationDegrees(album.la!)
let fromLocationLo: CLLocationDegrees = CLLocationDegrees(album.lo!)
var fromLocation: CLLocation = CLLocation(latitude: fromLocationLa, longitude: fromLocationLo)
let distance = fromLocation.distanceFromLocation(currentLocation)
if album.isActive == true {
if album.hasRange == true {
if distance < Double(album.range!) {
return true
}
else {
return false
}
}
else {
if currentCity == album.city {
return true
}
else {
return false
}
}
}
else {
return false
}
}
Update :
After a lot of trial and error, I found that adding a println() to get certain values prevents my bugs. For some reason something that isn't nil is turned into nil except for when I call println() just before using the value. Makes no sense to me....
As a guess, I think the optimizer is biting you. fromLocationLa, fromLocationLo, fromLocation, and distance are only used once. This means the following optimization can be done.
…
let fromLocationLa: CLLocationDegrees = CLLocationDegrees(album.la!)
let fromLocationLo: CLLocationDegrees = CLLocationDegrees(album.lo!)
var fromLocation: CLLocation = CLLocation(latitude: fromLocationLa, longitude: fromLocationLo)
let distance = fromLocation.distanceFromLocation(currentLocation)
if album.isActive == true {
if album.hasRange == true {
if distance < Double(album.range!) {
return true
}
else {
return false
}
}
…
optimized to
if album.isActive == true {
if album.hasRange == true {
return CLLocation(latitude: CLLocationDegrees(album.la!), longitude: CLLocationDegrees(album.lo!)).distanceFromLocation(currentLocation) < Double(album.range!)
}
This could explain the odd line number in the optimized code. It also put lots of implicit unwrapping on a single line.
Given the problems you seem to be having, a bit more care might be needed when unwrapping optionals.
let fromLocationLa: CLLocationDegrees? = album.la != nil ? CLLocationDegrees(album.la!) : nil
let fromLocationLo: CLLocationDegrees? = album.la != nil ? CLLocationDegrees(album.lo!) : nil
var fromLocation: CLLocation? = fromLocationLa != nil && fromLocationLo != nil ? CLLocation(latitude: fromLocationLa!, longitude: fromLocationLo!) : nil
let distance = fromLocation?.distanceFromLocation(currentLocation)
if album.isActive == true {
if album.hasRange == true {
if distance != nil && album.range != nil && distance! < Double(album.range!) {
return true
}
else {
return false
}
}
Related
Not sure why i'm getting this.. any suggestions would be grateful!
I ran into issues with my original coding where I had Firebase pod and Firebase Package.. so I started from scratch since that wasnt fixing itself.. now I get this.. and I am at a loss for how to resolve it.
static func fetchUsers() -> AnyPublisher<[UserProfile], Error> {
Future< [UserProfile], Error > { promise in
self.db.collection("Users")
.getDocuments { (snapshot, error) in
if let error = error {
promise(.failure(error))
return
}
guard let snapshot = snapshot else {
promise(.failure(FirebaseError.badSnapshot))
return
}
var users = [UserProfile]()
snapshot.documents.forEach { document in
print(users.count)
if let user = try? document.data(as: UserProfile.self){
if users.contains(where: { $0.id == user.id}) {return}
users.append(user)
} else {
print("Not working")
}
}
promise(.success(users))
}
}
.eraseToAnyPublisher()
}
I believe this is the syntax you're after:
var users = [UserProfile]()
users = snapshot.documents.compactMap { (document) -> UserProfile? in
if users.contains(where: { $0.id == user.id}) {
return nil
} else {
return try? document.data(as: UserProfile.self)
}
}
Also be aware that when you iterate something in Swift and encounter a false condition on an iteration, return will return out of the greater scope, not just that iteration. Therefore, use continue.
for x in y {
guard x > 0 else {
continue // continues loop
}
// ...
}
I'm running some regular edgePan code to initialise edgePan detection:
func setupGestures() {
let edgePan = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(screenEdgeSwiped))
edgePan.edges = .left
edgePan.cancelsTouchesInView = false
self.view.addGestureRecognizer(edgePan)
}
and the selector:
func screenEdgeSwiped(recognizer: UIScreenEdgePanGestureRecognizer) {
if recognizer.state == .recognized {
if slideOutMenuView != nil {
slideOutMenuView.show()
}
else {
print("THE SLIDE OUT MENU VIEW IS NIL")
}
}
}
This all works fine but when I give it a test run on the iPhone X. It seems to not even register the gesture.
Is there a different screenGesture that they have introduced or have they completely overwritten the functionality?
The App is in landscape mode.
Let's have two optional NSArrays. The goal is to check, if they are equal. My solution is
func isArrayEqualToArray(array1:NSArray?, array2:NSArray?) -> Bool {
let areBothEmpty:Bool = array1 == nil && array2 == nil
var areBothEqual:Bool
if !areBothEmpty && array2 != nil {
areBothEqual = array1?.isEqualToArray(array2!) ?? false
} else {
areBothEqual = false
}
let result = areBothEqual || areBothEmpty
return result
}
I feel that it is a little too verbose. It should be doable in a more concise and readable way. Does anyone have a better solution?
It is quite simple:
func isArrayEqualToArray(array1: NSArray?, array2: NSArray?) -> Bool {
return array1 == array2
}
does exactly what you want.
Why does it work? Here == is the operator that compares optionals
func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool
and that gives true if both operands are nil, or of both
operands are non-nil and the unwrapped operands are equal.
Also NSArray inherits from NSObject which conforms to Equatable,
and comparing NSObjects with == uses the isEqual: method, which is
implemented as isEqualToArray: on NSArray.
Therefore
array1 == array2
gives the same result as
array1.isEqualToArray(array2)
Yes, indeed, you don't need to overcomplicate things:
func isArrayEqualToArray(array1: NSArray?, array2: NSArray?) -> Bool {
if array1 == nil && array2 == nil {
return true;
}
if array1 != nil && array2 != nil {
return array1!.isEqualToArray(array2!);
}
return false;
}
Using a switch statement may be clearer:
func isArrayEqualToArray(a1: NSArray?, a2: NSArray?) -> Bool {
switch (a1,a2) {
case (.Some(a1),.Some(a2)):
return a1.isEqualToArray(a2)
case (.None,.None):
return true
default:
return false
}
}
I liked #The Paramagnetic Croiss answer but I'm still going to shorten it a bit because I see that I can.
```
func isArrayEqualToArray(array1: NSArray?, array2: NSArray?) -> Bool {
if array1 == array2 {
return true;
}
if array1 != nil && array2 != nil {
return array1!.isEqualToArray(array2!);
}
return false;
}
```
So I'm trying to use childNodeWithName to find a specific object of a custom class in didBeginContact, but it doesn't seem to see it. The println statement returns IAmAPortal1, but it doesn't find it when I try to search for it.
if(A == firstPort && B != playerCategory){
println(aBody!.name)
if let p1 = world.childNodeWithName("IAmAPortal1") as? Portal{
if p1.portalEstablished == false {
p1.portalEstablished = true
}
}
}
I have a list of Swift objects that I'd like to get sorted by multiple criteria. The objects in the list are of type DateRange:
class DateRange {
var from: NSDate?
var to: NSDate?
}
The list contains many of these objects where some from or to fields are nil. I want to have this list sorted by:
First all objects that have dates
Then objects that have at least one date (either from or to)
And at the very end objects without any
The dates itself don't matter, just their existence. In Ruby I could do this (if the date is nil I set it to a very low date):
date_ranges.sort { |a, b|
[fix_nil(a.from), fix_nil(a.to)] <=> [fix_nil(b.from), fix_nil(b.to)]
}.reverse
def fix_nil(val)
val.nil? ? Date.new(0) : val
end
What's the best way to do this with Swift? Thanks in advance.
Seems like it might be a good idea to add a dateCount computed property to your DateRange type. This would be a good time for pattern matching:
extension DateRange {
// returns the number of non-nil NSDate members in 'from' and 'to'
var dateCount: Int {
switch (from, to) {
case (nil, nil): return 0
case (nil, _): return 1
case (_, nil): return 1
default: return 2
}
}
}
Then you can sort your list with a simple closure:
var ranges = [DateRange(nil, nil), DateRange(NSDate(), nil), DateRange(nil, NSDate()), DateRange(nil, nil), DateRange(NSDate(), NSDate())]
ranges.sort { $0.dateCount > $1.dateCount }
If you wanted, you could even make it Comparable with a few more lines:
extension DateRange : Comparable { }
func ==(lhs: DateRange, rhs: DateRange) -> Bool {
return lhs.dateCount == rhs.dateCount
}
func <(lhs: DateRange, rhs: DateRange) -> Bool {
return lhs.dateCount > rhs.dateCount
}
This lets you sort your list properly with an operator argument:
ranges.sort(<)
I presume that by list you mean array, so I am basing my answer on that assumption.
You can use the sort method of the array struct, which takes a closure having this signature:
(lhs: T, rhs: T) -> Bool
returning true if lhs is less than rhs, false otherwise.
I came up with this implementation:
var x: [DateRange]
// ... initialize the array
x.sort { (lhs: DateRange, rhs: DateRange) -> Bool in
if lhs.from != nil && lhs.to != nil {
return true
}
if lhs.from == nil && lhs.to == nil {
return false
}
return rhs.from == nil && rhs.to == nil
}
if lhs has both properties not nil, then it comes first, regardless of rhs
if lhs has both properties nil, then if comes after, regardless of rhs
else lhs has one nil, the other not nil, and in that case it comes first only if rhs has both properties nil
If you plan to reuse the sort in several places, it's better to move the code out of the sort method - the best place is probably an overload of the < operator:
func < (lhs: DateRange, rhs: DateRange) -> Bool {
if lhs.from != nil && lhs.to != nil {
return true
}
if lhs.from == nil && lhs.to == nil {
return false
}
return rhs.from == nil && rhs.to == nil
}
and in that case it can be used as follows:
x.sort(<)
If you don't like the operator overload, you can of course give that function any other name.
Note that sorting is done in place.
Here is how I would approach this. To keep things simple, add a scoring function for the date range. In your scenario, you have 3 possibilities:
nil & nil : 0 points
nil & date : 1 point
date & date : 2 points
import Foundation
class DateRange {
var from: NSDate?
var to: NSDate?
init(from: NSDate?, to: NSDate?)
{
self.from = from
self.to = to
}
func scoreDateRange() -> Int
{
var score = 0
if from != nil
{
score++
}
if to != nil
{
score++
}
return score
}
}
func sortDateRange( d1 : DateRange, d2 : DateRange)-> Bool
{
return d1.scoreDateRange() > d2.scoreDateRange()
}
var date_ranges = [DateRange]()
date_ranges.append(DateRange(from:nil, to:nil))
date_ranges.append(DateRange(from:nil, to:nil))
date_ranges.append(DateRange(from:NSDate(), to:NSDate()))
date_ranges.append(DateRange(from:nil, to:NSDate()))
date_ranges.append(DateRange(from:NSDate(), to:nil))
date_ranges.append(DateRange(from:NSDate(), to:NSDate()))
date_ranges.sort(sortDateRange)