EXC_BAD_ACCESS Code=2 Swift iOS - ios

When developing an iOS app I come across random (sometimes occurring, sometimes not) EXC_BAD_ACCESS error in the following code:
import UIKit
class OrderTripDetailsController: UIViewController, OrderAware {
var order: Order?
var orderService = OrderService()
// MARK: Properties
#IBOutlet weak var driverName: UILabel!
#IBOutlet weak var autoColor: UILabel!
#IBOutlet weak var autoPlates: UILabel!
#IBOutlet weak var autoBrandModel: UILabel!
#IBOutlet weak var map: YMKMapView!
// MARK: Actions
// MARK: Navigation
override func viewDidLoad() {
if let cab = order?.orderCab {
autoColor.text = cab.cab.auto.color.name
autoPlates.text = cab.cab.auto.plates
driverName.text = cab.cab.driver.fullname
autoBrandModel.text = "\(cab.cab.auto.brand) \(cab.cab.auto.model)"
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
orderService.controllerDelegate = self
orderService.startSync()
}
override func viewWillDisappear(animated: Bool) {
orderService.stop() // <-- this is the line that fails
super.viewWillDisappear(animated)
}
// MARK: Order Aware
func setOrder(order: Order){
self.order = order
}
}
OrderService
Order Service is a class that starts timer and stops it. After stop is called, sometimes EXC_BAD_ACCESS occurs
import Locksmith
import RealmSwift
class OrderService {
// MARK: delegates
var controllerDelegate: UIViewController?
// Get the default Realm
let realm = try! Realm()
var timer = NSTimer()
//MARK: Domain actions
//repeat every n time if any dfound
#objc func initOrderSync(timer:NSTimer) {
func onRemoteReceived (order: Order) -> Void {
debugPrint("remote received", order.id)
if let o = realm.objectForPrimaryKey(OrderPo.self, key: order.orderHash) {
if o.orderStatus != order.orderStatus {
debugPrint("order status updated", order.id, order.orderStatus)
OrderUtils.navigateToOrderStatus(order,
viewController: controllerDelegate!)
}
try! realm.write {
o.orderStatus = order.orderStatus
}
}
}
if let authToken = AuthUtils.getToken() {
let orders = getOrdersByStatuses(OrderUtils.activeStatuses)
if orders.count > 0 {
for o in orders {
OrderRemoteService().getOrderFromRemote(o.id!, token: authToken, callback: onRemoteReceived)
}
} else {
debugPrint("invalidating timer; no orders")
stop()
}
} else {
debugPrint("invalidating timer; no auth")
stop()
}
}
func startSync() {
if !self.timer.valid {
debugPrint("starting order sync", controllerDelegate?.restorationIdentifier)
self.timer = NSTimer.scheduledTimerWithTimeInterval(20, target: self, selector: Selector("initOrderSync:"), userInfo: nil, repeats: true)
} else {
debugPrint("sync is already started", controllerDelegate?.restorationIdentifier)
}
}
func stop() {
dispatch_async(GlobalMainQueue, {
if self.timer.valid {
self.timer.invalidate()
debugPrint("invalidated timer", self.controllerDelegate?.restorationIdentifier)
} else {
debugPrint("sync is already stopped", self.controllerDelegate?.restorationIdentifier)
}
})
}
// MARK: orders
func getOrders() -> Results<OrderPo> {
return try! realm.objects(OrderPo.self).sorted("orderTime")
}
func getOrdersByStatuses(statuses: [String]) -> Results<OrderPo> {
var qString = "'\(statuses.first!)'"
if statuses.count > 1 {
for s in 1...statuses.count-1 {
qString += ",'\(statuses[s])'"
}
}
return try! realm.objects(OrderPo.self).filter("orderStatus IN {\(qString)}").sorted("orderTime")
}
}
Could anyone help with any ideas why it might happen?
Update 20.08.2016
Found out that OrderService is being deinitialised after 10 seconds for some reason.

Related

How to create a class instance in Observer pattern?

I implemented an observer pattern in the below code. However, I am not sure how to create SeasonSubject class's instance in order to call addObserver() function?
I don't want to create it inside my view controller. Please refer to below code.
//
// SeasonViewController.swift
// PhotoCalender
//
// Created by Suraj M Gaikwad on 09/07/21.
//
import UIKit
enum Season: String {
case summer
case winter
case monsoon
case none
}
protocol SeasonObserver {
func onSeasonChange(_season: Season)
}
class PhotoframeObserver: SeasonObserver {
var delegate: SeasonViewControllerDelegate?
init(_delegate: SeasonViewControllerDelegate) {
delegate = _delegate
}
func onSeasonChange(_season: Season) {
switch _season {
case .monsoon, .summer, .winter:
delegate?.changeTheLayoutPer(_season: _season)
case .none:
debugPrint("none")
}
}
}
class PhotoDetailsObserver: SeasonObserver {
var delegate: SeasonViewControllerDelegate?
init(_delegate: SeasonViewControllerDelegate) {
delegate = _delegate
}
func onSeasonChange(_season: Season) {
switch _season {
case .monsoon, .summer, .winter:
delegate?.changeTheTitle(_season: _season)
case .none:
debugPrint("none")
}
}
}
protocol SeasonSubjectProtocol {
func informTheSeasonChange(_season: Season)
}
class SeasonSubject: SeasonSubjectProtocol {
private var _season = Season.none
var changedSeason: Season {
get {
_season
}
set {
_season = newValue
}
}
private var seasonObserver = [SeasonObserver]()
func addObserver(_observer: SeasonObserver) {
seasonObserver.append(_observer)
}
func removeObserver(_observer: SeasonObserver) {
// seasonObserver.remove(at: 0)
}
private func notifyObserver() {
seasonObserver.forEach { $0.onSeasonChange(_season: _season)
}
}
func informTheSeasonChange(_season: Season) {
changedSeason = _season
}
deinit {
seasonObserver.removeAll()
}
}
protocol SeasonViewControllerDelegate {
func changeTheLayoutPer(_season: Season)
func changeTheTitle(_season: Season)
}
class SeasonViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var backgroundView: UIView!
#IBOutlet weak var seasonTitle: UILabel!
var delegate: SeasonSubjectProtocol?
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
self.imageView.image = UIImage()
self.backgroundView.backgroundColor = .white
self.seasonTitle.text = "none"
}
#IBAction func changeTheSeason(_ sender: UIButton) {
if count > 2 {
count = 0
return
}
if count == 0 {
delegate?.informTheSeasonChange(_season: Season.summer)
}
if count == 1 {
delegate?.informTheSeasonChange(_season: Season.winter)
}
if count == 2 {
delegate?.informTheSeasonChange(_season: Season.monsoon)
}
count += 1
}
}
extension SeasonViewController: SeasonViewControllerDelegate {
func changeTheLayoutPer(_season: Season) {
switch _season {
case .monsoon:
self.imageView.image = UIImage()
self.backgroundView.backgroundColor = .gray
case .summer:
self.imageView.image = UIImage()
self.backgroundView.backgroundColor = .orange
case .winter:
self.imageView.image = UIImage()
self.backgroundView.backgroundColor = .blue
case .none:
debugPrint("none")
self.imageView.image = UIImage()
self.backgroundView.backgroundColor = .white
}
}
func changeTheTitle(_season: Season) {
switch _season {
case .monsoon, .summer, .winter, .none:
self.seasonTitle.text = _season.rawValue
}
}
}
I want to create an instance of SeasonSubject() class. I want to call addObserver & removeObserver() methods.
You can create SeasonSubject as a singleton instance, it already maintains an array of observers so multiple observers can use this same instance throughout the app.
class SeasonSubject: SeasonSubjectProtocol {
static let shared = SeasonSubject()
}
All you need to do now is - call addObserver / removeObserver on this singleton instance from the places you want.
class ViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
SeasonSubject.shared.addObserver(self)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
SeasonSubject.shared.removeObserver(self)
}
}
CAUTION : You must make sure these add/remove calls are balanced otherwise you will fall into the trap of observers never getting deallocated.
If you want to stay away from this problem - you should consider a NotificationCenter based implementation where your observers are never at risk of being retained in memory forever.

How to randomly print a word in an iOS app?

I have been trying to create an app that randomly prints a new word after a certain amount of time, i.e five seconds.
import UIKit
class ViewController: UIViewController {
var myTimer : Timer!
var theValue = 0
#IBOutlet weak var textLabel: UILabel!
#IBOutlet weak var InspireLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
}
override func viewDidDisappear(_ animated: Bool) {
self.myTimer.invalidate()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#objc func updateMyLabel() {
theValue += 1
self.textLabel.text = String(theValue)
}
func randomText() -> String {
if theValue > 5 {
let words = ["Place", "Cat", "House"]
return words.randomElement() ?? "" //Use default method to get random element from Array
}
return "string if theValue < 5 or equal to 5"
}
#IBAction func ResetButton(_ sender: Any) {
self.myTimer.invalidate()
theValue = 0
self.textLabel.text = String(theValue)
}
#IBAction func PauseButton(_ sender: Any) {
self.myTimer.invalidate()
}
#IBAction func PlayButton(_ sender: Any) {
self.myTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateMyLabel), userInfo: nil, repeats: true)
}
}
This is all the code I have right now. As you can probably tell I'm new too StackExchange and so please excuse any breach in etiquette.
it's giving an error because you forgot to add else part in your code.
func randomText() -> String {
if theValue > 5 {
let words = ["Place", "Cat", "House"]
return words.randomElement() ?? "" //Use default method to get random element from Array
}
return "string if theValue < 5 or equal to 5"
}

My custom RxDelegateProxy immediately disposing

I have some third party library that has delegate methods. But I like using RX so I should create RxDelegateProxy to receive delegate's callbacks via RX.
Here my custom DelegateProxy class:
extension Reactive where Base:GalleryController {
var selectedImages:Observable<(GalleryController, [Image])> {
let proxy = RxGalleryDelegateProxy.createProxy(for: self.base)
return proxy.imageSubject.asObservable()
}
}
private class RxGalleryDelegateProxy: DelegateProxy<GalleryController, GalleryControllerDelegate>, DelegateProxyType, GalleryControllerDelegate {
private var _imageSubject: PublishSubject<(GalleryController, [Image])>?
public weak fileprivate(set) var galleryController: GalleryController?
internal var imageSubject: PublishSubject<(GalleryController, [Image])> {
if let subject = _imageSubject {
return subject
}
let subject = PublishSubject<(GalleryController, [Image])>()
_imageSubject = subject
return subject
}
static func currentDelegate(for object: GalleryController) -> GalleryControllerDelegate? {
return object.delegate
}
static func setCurrentDelegate(_ delegate: GalleryControllerDelegate?, to object: GalleryController) {
object.delegate = delegate
}
static func registerKnownImplementations() {
self.register { RxGalleryDelegateProxy(parentObject: $0) }
}
private init(parentObject: GalleryController) {
self.galleryController = castOrFatalError(parentObject)
super.init(parentObject: parentObject, delegateProxy: RxGalleryDelegateProxy.self)
}
func galleryController(_ controller: GalleryController, didSelectImages images: [Image]) {
if let subject = _imageSubject {
subject.on(.next((controller, images)))
}
self._setForwardToDelegate(galleryController(controller, didSelectImages: images), retainDelegate: true)
}
deinit {
_imageSubject?.on(.completed)
}
}
In my UIViewController I subscribe with:
final class PhotoLibraryViewController: UIViewController {
private let _bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let gallery = GalleryController()
present(gallery, animated: true, completion: nil)
gallery.rx.selectedImages
.debug("--------")
.observeOn(MainScheduler.instance)
.subscribe(onNext: { (controller, images) in
print("\(images)")
}, onError: { (error) in
DDLogError("Error:\n\(error)")
})
.disposed(by: _bag)
}
}
But all I get in console output via .debug("--------") is:
2018-01-09 20:05:14.814: -------- -> subscribed
2018-01-09 20:05:14.817: -------- -> Event completed
2018-01-09 20:05:14.817: -------- -> isDisposed
So my object is immediately disposing just after creation. What did I do wrong?
Your gallery object is created inside viewDidLoad(), so once viewDidLoad() is completed, the deinit method from gallery is called and it is disposed.
Move your gallery object out of the viewDidLoad():
final class PhotoLibraryViewController: UIViewController {
private let _bag = DisposeBag()
let gallery = GalleryController()
override func viewDidLoad() {
super.viewDidLoad()
present(gallery, animated: true, completion: nil)
gallery.rx.selectedImages
.debug("--------")
.observeOn(MainScheduler.instance)
.subscribe(onNext: { (controller, images) in
print("\(images)")
}, onError: { (error) in
DDLogError("Error:\n\(error)")
})
.disposed(by: _bag)
}
}

EXC_BAD_ACESS crash xcode

I'm getting this crash : link
in my app ,i did many search abou it but i didn't find how to solve it.
i also enabled Zombies object & Analyzer of xcode but without succes.
Here is my code :
import UIKit
class CameraViewController: UIViewController{
#IBOutlet weak var playerContainer: UIView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var loading: UIActivityIndicatorView!
var device : GTLUserendpointGeneralCamera!
var myfoxCam : CloseliCameraDevice!
var retryToPlayCount = 0
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self,selector: "playerStatusChanged:",name: CameraPlayerStatusChangedNotification,object: nil)
NSNotificationCenter.defaultCenter().addObserver(self,selector: "playerStoppedDispose:",name: CameraPlayerStoppedNotification,object: nil)
}
override func viewDidAppear(animated: Bool) {
if(device.brand == "myfox"){
showLive()
}
}
override func viewWillDisappear(animated: Bool) {
MyFoxManager.sharedInstance.destroyPlayer()
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func showLive(){
loading.startAnimating()
MyFoxManager.sharedInstance.showLive(myfoxCam , image: self.imageView)
}
func playerStatusChanged(notification: NSNotification){
let waiting = notification.userInfo!["NSLocalizedDescription"] as! Bool
dispatch_async(dispatch_get_main_queue()) { [weak self] in
if let strongSelf = self {
if(waiting){
strongSelf.loading.startAnimating()
}else{
strongSelf.retryToPlayCount = 0
strongSelf.loading.stopAnimating()
}
}
}
}
func playerStoppedDispose(notification: NSNotification){
let code = notification.userInfo!["NSLocalizedFailureReason"] as! Int
dispatch_async(dispatch_get_main_queue()) { [weak self] in
if let strongSelf = self {
if(code & strongSelf.retryToPlayCount < 4){
strongSelf.retryToPlayCount = strongSelf.retryToPlayCount + 1
strongSelf.performSelector("showLive", withObject: nil, afterDelay: 2.0)
}
}
}
}
}
And
import UIKit
import Foundation
import CoreBluetooth
class MyFoxManager: NSObject {
static let sharedInstance = MyFoxManager()
var closeSDK : CloseliSDK!
var login = false
private override init() {
closeSDK = CloseliSDK(productKey: MyFoxAppId, withPassword: MyFoxAppSecret, serverType: "us")
}
func getCamera(device: GTLUserendpointGeneralCamera) -> CloseliCameraDevice? {
if(!login){
do {
try closeSDK.loginWithToken(device.appUrl, withAccount: device.url)
login = true
}catch{
return nil
}
}
do {
let myfoxCameras = try closeSDK.getCameraListError()
let myfoxCamera = myfoxCameras.filter{$0.deviceUUID == device.idDevice}
return myfoxCamera[0] as? CloseliCameraDevice
}catch {
return nil
}
}
func showLive(myfoxCam: CloseliCameraDevice, image: UIImageView){
closeSDK.preparetoLivePreview(myfoxCam , withUI: image)
}
func destroyPlayer(){
closeSDK.destoryPlayer()
}
}
Notification definition from third-party library :
/**
Notification for live preview status changing.
NOTICE: The notification may not be sent by CloseliSDK, so please fill parameter with sender to nil when adding observer
#param userInfo in NSNotification is a NSDictionary, value for NSLocalizedDescriptionKey is a NSNumber, YES means live preview is buffering, NO means live preview begin.
BOOL bWaiting = [[[notification userInfo] valueForKey:NSLocalizedDescriptionKey] boolValue];
*/
extern NSString *const CameraPlayerStatusChangedNotification;
/**
Notification for player stopped.
NOTICE: The notification may not be sent by CloseliSDK, so please fill parameter with sender to nil when adding observer
#param userInfo in NSNotification is a NSDictionary, value for NSLocalizedFailureReasonErrorKey is a NSNumber, represent the reason why it stopped, normally 0.
long stopReason = [[[notification userInfo] valueForKey:NSLocalizedFailureReasonErrorKey] longValue];
stopReason: 0x3261-means there is another client playing in p2p mode.
*/
extern NSString *const CameraPlayerStoppedNotification;
Any idea ?
Thanks in advance

Swift Barcode Scanning

I am attempting add barcode scanning to my app using RSBarcodes. I'm having two issues: Not being able to update a label that displays the barcode scanned and the delegate to send the barcode to my calling view controller not working. Below is my code for the view controller that handles the scanning:
import UIKit
import AVFoundation
import RSBarcodes
class ScanViewController: RSCodeReaderViewController {
#IBOutlet weak var label1Label: UILabel!
#IBOutlet weak var label2Label: UILabel!
#IBOutlet weak var scanLabel: UIButton!
var delegate: barcodesScannedDelegate?
var codes:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
var code=""
// Do any additional setup after loading the view.
focusMarkLayer.strokeColor = UIColor.redColor().CGColor
cornersLayer.strokeColor = UIColor.yellowColor().CGColor
tapHandler = { point in
//println(point)
}
barcodesHandler = { barcodes in
for barcode in barcodes {
if !contains(self.codes, barcode.stringValue) {
self.codes.append(barcode.stringValue)
code = barcode.stringValue
}
}
println(code)
self.label1Label.text = code
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func finishedPressed(sender: UIButton) {
delegate?.barcodesScanned(self.codes)
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func cancelPressed(sender: UIButton) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Just to ensure I did the delegate correctly, here is my code in Protocol.swift:
protocol selectCarrierDelegate {
func selectCarrier(carrierID: String,carrier: String)
}
protocol barcodesScannedDelegate {
func barcodesScanned(barcodes: [String])
}
And the relevant code in the controller that should receive the barcode:
class InBoundViewController: UIViewController,selectCarrierDelegate,UIAlertViewDelegate,UITableViewDelegate,UITableViewDataSource,barcodesScannedDelegate {
func barcodesScanned(barcodes: [String]) {
println("codes=\(barcodes)")
}
Anyone have any ideas why the label won't change and the delegate isn't working?
You need to update all UI in the main thread.
Try this:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.label1Label.text = code
})
Swift 4:
DispatchQueue.main.async {
self.label1Label.text = code
}

Resources