I have a project in which I am using both objective-c and swift, not sure if this is relevant but might be.
I have a class defined as follows:
#objc public class BHCloudFileManager {
...
}
This class is a singleton and so has a property:
public class var sharedManager: BHCloudFileManager {
struct Singleton {
static let instance = BHCloudFileManager()
}
return Singleton.instance
}
And also declares an instance variable as such:
var cloudFilesAwaitingUpload: [BHCloudFile] = [] // crash happens on this line
It might be worth mentioning that BHCloudFile is an objective-c class whereas BHCloudFileManager is clearly a swift class. The sharedManager method is first called on launch from objective-c code.
Prior to my updating my Mac to Yosemite (there may have also been an Xcode upgrade but I'm not sure) this code all worked fine, but now I get a crash on the property initialisation line. My init() method appends to this array, but that shouldn't be an issue, should it?
If you have any idea what might be causing this it would be greatly appreciated, I'm at a bit of a loose end!
Platform:
Occurs on iOS 7.1 on an iPad 3rd gen. Does not occur on iOS 8.1 in the simulator.
Exception:
Thread 1: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
Stack trace:
0 0x2bec10c4 in dyld_fatal_error ()
1 0x2bec1f06 in dyld::halt(char const*) ()
2 0x2bec369e in dyld::fastBindLazySymbol(ImageLoader**, unsigned long) ()
3 0x3b0e40d0 in dyld_stub_binder ()
4 0x0005346c in Sparkjar.BHCloudFileManager.init (Sparkjar.BHCloudFileManager.Type)() -> Sparkjar.BHCloudFileManager at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/models/BHCloudFileManager.swift:22
5 0x00053328 in Sparkjar.BHCloudFileManager.__allocating_init (Sparkjar.BHCloudFileManager.Type)() -> Sparkjar.BHCloudFileManager ()
6 0x000532e8 in globalinit_func1 at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/models/BHCloudFileManager.swift:30
7 0x0185902a in __swift_once_block_invoke ()
8 0x3b0bf81e in _dispatch_client_callout ()
9 0x3b0c760e in dispatch_once_f$VARIANT$mp ()
10 0x01859016 in swift_once ()
11 0x0005d4c0 in Sparkjar.BHCloudFileManager.(sharedManager.getter : Sparkjar.BHCloudFileManager).(Singleton #1).instance.mutableAddressor : Sparkjar.BHCloudFileManager at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/models/BHCloudFileManager.swift:30
12 0x000532b8 in Sparkjar.BHCloudFileManager.sharedManager.getter : Sparkjar.BHCloudFileManager at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/models/BHCloudFileManager.swift:32
13 0x000533b0 in #objc Sparkjar.BHCloudFileManager.sharedManager.getter : Sparkjar.BHCloudFileManager ()
14 0x00170570 in -[BHAppDelegate setupApplication] at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/BHAppDelegate.m:54
15 0x00170414 in -[BHAppDelegate application:didFinishLaunchingWithOptions:] at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/BHAppDelegate.m:41
16 0x327b95a6 in -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] ()
17 0x327b8efa in -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] ()
18 0x327b358a in -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] ()
19 0x3274f708 in -[UIApplication handleEvent:withNewEvent:] ()
20 0x3274e870 in -[UIApplication sendEvent:] ()
21 0x327b2cc8 in _UIApplicationHandleEvent ()
22 0x34d95aec in _PurpleEventCallback ()
23 0x34d956d6 in PurpleEventCallback ()
24 0x2fef8ab6 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
25 0x2fef8a52 in __CFRunLoopDoSource1 ()
26 0x2fef7226 in __CFRunLoopRun ()
27 0x2fe61f4e in CFRunLoopRunSpecific ()
28 0x2fe61d32 in CFRunLoopRunInMode ()
29 0x327b1ef0 in -[UIApplication _run] ()
30 0x327ad16c in UIApplicationMain ()
31 0x001ab948 in main at /Users/georgegreen/Code/BeeHive/BeeHive/BeeHive/main.m:16
Related
First post here!
I have an NSScrollView subclass. I want a mouse's option-scrollwheel events to cause the same zooming that trackpad pinch-zooming causes. I tried the simple solution below, but that just causes lots of assertions, probably because the scroll event is the wrong type and doesn't have the needed data for a magnify event. I don't see handy NSEvent class methods for creating magnification events, like they offer for mouse, key, enter/exit, and other events.
-(void) scrollWheel:(NSEvent*)event
{
if(event.modifierFlags & NSAlternateKeyMask)
[self magnifyWithEvent:event];
else
[super scrollWheel:event];
}
Error output:
2018-01-18 11:35:59.509 BoF[71240:2227373] -_continuousScroll is deprecated for NSScrollWheel. Please use -hasPreciseScrollingDeltas.
2018-01-18 11:35:59.509 BoF[71240:2227373] -deviceDeltaX is deprecated for NSScrollWheel. Please use -scrollingDeltaX.
2018-01-18 11:35:59.509 BoF[71240:2227373] -deviceDeltaY is deprecated for NSScrollWheel. Please use -scrollingDeltaY.
2018-01-18 11:35:59.509 BoF[71240:2227373] *** Assertion failure in -[NSEvent magnification], /SourceCache/AppKit/AppKit-1348.17/AppKit.subproj/NSEvent.m:1890
2018-01-18 11:35:59.509 BoF[71240:2227373] Invalid message sent to event "NSEvent: type=ScrollWheel loc=(371,197) time=80177.1 flags=0x80120 win=0x6180001f8000 winNum=3959 ctxt=0x0 deltaX=0.000000 deltaY=0.400024 deltaZ=0.000000 deviceDeltaX=0.000000 deviceDeltaY=3.000000 deviceDeltaZ=0.000000 count:0 phase=Changed momentumPhase=None"
2018-01-18 11:35:59.643 BoF[71240:2227373] (
0 CoreFoundation 0x00007fff90c6e03c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8282176e objc_exception_throw + 43
2 CoreFoundation 0x00007fff90c6de1a +[NSException raise:format:arguments:] + 106
3 Foundation 0x00007fff8632897b -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
4 AppKit 0x00007fff8f96c8c2 -[NSEvent magnification] + 182
5 AppKit 0x00007fff8f96c488 -[NSScrollView magnifyWithEvent:] + 395
6 BoF 0x000000010002ceb3 -[ComicScrollView scrollWheel:] + 99
7 AppKit 0x00007fff8f7c4cfb forwardMethod + 126
8 AppKit 0x00007fff8f8f5d00 -[NSView scrollWheel:] + 507
9 AppKit 0x00007fff8f7c4cfb forwardMethod + 126
10 AppKit 0x00007fff8f8f5d00 -[NSView scrollWheel:] + 507
11 AppKit 0x00007fff8fe3b6cc -[NSWindow _reallySendEvent:isDelayedEvent:] + 6941
12 AppKit 0x00007fff8f7ccc86 -[NSWindow sendEvent:] + 470
13 AppKit 0x00007fff8f7c9137 -[NSApplication sendEvent:] + 2285
14 AppKit 0x00007fff8f6f2b68 -[NSApplication run] + 711
15 AppKit 0x00007fff8f66f244 NSApplicationMain + 1832
16 BoF 0x000000010000f232 main + 34
17 libdyld.dylib 0x00007fff848f95c9 start + 1
18 ??? 0x0000000000000003 0x0 + 3
)
Well, it's not using the standard magnifyWithEvent: code path, but it works to fake it like so, making assumptions about the multiplier to convert the scroll amount to a magnification amount.
-(void) scrollWheel:(NSEvent*)event
{
if(event.modifierFlags & NSAlternateKeyMask) {
NSPoint pt = [self.documentView convertPoint:event.locationInWindow fromView:nil];
CGFloat by = event.scrollingDeltaY * 0.001; // The smallest pinch-zoom amount seems to be about 0.002, but that was a bit too coarse.
if(!event.hasPreciseScrollingDeltas)
by *= self.verticalLineScroll;
[self setMagnification:self.magnification + by centeredAtPoint:pt];
}
else
[super scrollWheel:event];
}
One possible Swift 5 version, better with quadratic magnification:
override func scrollWheel(with event: NSEvent) {
if !event.momentumPhase.isEmpty || !event.phase.isEmpty {
// magic trackpad or magic mouse
super.scrollWheel(with: event)
} else if event.modifierFlags.contains(.option) {
// traditional mouse
if let centerPoint = documentView?.convert(event.locationInWindow, from: nil) {
let linearVal = CGFloat(log2(magnification))
var linearDeltaY = event.scrollingDeltaY * 0.01
if !event.hasPreciseScrollingDeltas {
linearDeltaY *= verticalLineScroll
}
setMagnification(CGFloat(pow(2, linearVal + linearDeltaY)), centeredAt: centerPoint)
}
}
}
My app is essentially a collection of cards, each with various messages/information on it. One swipes to go through these cards, generally swiping right. I am currently getting this sig abrt error:
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
It also prints, this:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[filterPageViewController askForPushNotifications]: unrecognized selector sent to instance 0x7f8b6d0acd80'
*** First throw call stack:
(
0 CoreFoundation 0x000000010fa92d85 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010f506deb objc_exception_throw + 48
2 CoreFoundation 0x000000010fa9bd3d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010f9e1cfa ___forwarding___ + 970
4 CoreFoundation 0x000000010f9e18a8 _CF_forwarding_prep_0 + 120
5 Lettuce 0x000000010a2780a6 -[DraggableViewBackground cardSwipedRight:] + 2470
6 Lettuce 0x000000010a2d0ad5 -[DraggableView rightAction] + 453
7 Lettuce 0x000000010a2d02ed -[DraggableView afterSwipeAction] + 77
8 Lettuce 0x000000010a2cfe22 -[DraggableView beingDragged:] + 1922
9 UIKit 0x000000010d9c7b28 _UIGestureRecognizerSendTargetActions + 153
10 UIKit 0x000000010d9c419a _UIGestureRecognizerSendActions + 162
11 UIKit 0x000000010d9c2197 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 843
12 UIKit 0x000000010d9ca655 ___UIGestureRecognizerUpdate_block_invoke898 + 79
13 UIKit 0x000000010d9ca4f3 _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 342
14 UIKit 0x000000010d9b7e75 _UIGestureRecognizerUpdate + 2634
15 UIKit 0x000000010d54448e -[UIWindow _sendGesturesForEvent:] + 1137
16 UIKit 0x000000010d5456c4 -[UIWindow sendEvent:] + 849
17 UIKit 0x000000010d4f0dc6 -[UIApplication sendEvent:] + 263
18 UIKit 0x000000010d4ca553 _UIApplicationHandleEventQueue + 6660
19 CoreFoundation 0x000000010f9b8301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
20 CoreFoundation 0x000000010f9ae22c __CFRunLoopDoSources0 + 556
21 CoreFoundation 0x000000010f9ad6e3 __CFRunLoopRun + 867
22 CoreFoundation 0x000000010f9ad0f8 CFRunLoopRunSpecific + 488
23 GraphicsServices 0x00000001107e2ad2 GSEventRunModal + 161
24 UIKit 0x000000010d4cff09 UIApplicationMain + 171
25 Lettuce 0x000000010a2c3f0f main + 111
26 libdyld.dylib 0x000000011012492d start + 1
27 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
After some investigating, I have found the problematic code. It is a line within my cardSwipedRight method that is in my draggableviewbackground class (this class functions as a deck, to hold all of the cards) :
[((settingsTableViewController *)([obj.superNavController.viewControllers[obj.profileNum] viewControllers][0])) askForPushNotifications];
This line of code is within an if statement that checks whether this is a "sign me up for notifications card". What I'm confused by, is why xcode associated filterPageView with askForPushNotifications. Not only does filterPageView not have a askForPushNotifications method, but I don't swipe right on filterPageView nor have I viewed it by the time my app crashes.
One receives an unrecognized selector exception when the object to which the selector is sent does not implement/respond to the sent selector. In simple words, if a class A does not implement a method and someone try to call that method on an object of class A, runtime throws an unrecognized selector exception.
When we are not sure whether an object will respond to a selector, we should have a safety check to see if an object responds to intended selector.
For eg.
if ([*obj* respondsToSelector:#selector(*selector*)])
{
[*obj* performSelector:*selector*];
}
unrecognized selector sent to instance comes up when you try to call a method on an object but that method doesn't exist (The corrrect terminology is that you have tried to send a message called "askForPushNotifications" but the settingsTableViewController does not understand it as it(askForPushNotifications) doesn't exit . I am sure you may not have that method in your settingsTableViewController. Please check and let me know if that helped you.
Also, please check with respondsToSelector if the object actually responds to the method askForPushNotifications. It may be the case that
((settingsTableViewController
*)([obj.superNavController.viewControllers[obj.profileNum] viewControllers][0]))
may not be of type SettingsTableViewController. Please check
if [(((settingsTableViewController *)([obj.superNavController.viewControllers[obj.profileNum] viewControllers][0])) respondsToSelector:#selector(askForPushNotifications)]
{
[((settingsTableViewController *)([obj.superNavController.viewControllers[obj.profileNum] viewControllers][0])) askForPushNotifications];
}
This question already has answers here:
Xcode - How to fix 'NSUnknownKeyException', reason: … this class is not key value coding-compliant for the key X" error?
(79 answers)
Closed 7 years ago.
I have an XCode Project which I was developing in objective C but now with Swift I have a few classes saved as .swift files. When I am referencing these as custom classes in the Interface Builder, they don't work and I get an error that the class doesn't exist.
What am I missing in terms of bridging the gap between the two? I have the header file to make the objective C available to Swift but not sure about the other way around
Thanks
2014-07-08 20:18:07.463 FoodForTeeth[22030:70b] Unknown class SecondViewController in Interface Builder file.
2014-07-08 20:18:07.496 FoodForTeeth[22030:70b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x8c85390> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key date.'
*** First throw call stack:
(
0 CoreFoundation 0x01acf5e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x018528b6 objc_exception_throw + 44
2 CoreFoundation 0x01b5f6a1 -[NSException raise] + 17
3 Foundation 0x01513c2e -[NSObject(NSKeyValueCoding) setValue:forUndefinedKey:] + 282
4 Foundation 0x0147ff3b _NSSetUsingKeyValueSetter + 88
5 Foundation 0x0147f493 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 267
6 Foundation 0x014e194a -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 412
7 UIKit 0x00866cd5 -[UIRuntimeOutletConnection connect] + 106
8 libobjc.A.dylib 0x018647d2 -[NSObject performSelector:] + 62
9 CoreFoundation 0x01acab6a -[NSArray makeObjectsPerformSelector:] + 314
10 UIKit 0x0086582e -[UINib instantiateWithOwner:options:] + 1417
11 UIKit 0x006d7c95 -[UIViewController _loadViewFromNibNamed:bundle:] + 280
12 UIKit 0x006d843d -[UIViewController loadView] + 302
13 UIKit 0x006d873e -[UIViewController loadViewIfRequired] + 78
14 UIKit 0x006d8c44 -[UIViewController view] + 35
15 UIKit 0x006f2a72 -[UINavigationController _startCustomTransition:] + 778
16 UIKit 0x006ff757 -[UINavigationController _startDeferredTransitionIfNeeded:] + 688
17 UIKit 0x00700349 -[UINavigationController __viewWillLayoutSubviews] + 57
18 UIKit 0x0083939d -[UILayoutContainerView layoutSubviews] + 213
19 UIKit 0x0062fdd7 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
20 libobjc.A.dylib 0x0186481f -[NSObject performSelector:withObject:] + 70
21 QuartzCore 0x045ab72a -[CALayer layoutSublayers] + 148
22 QuartzCore 0x0459f514 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
23 QuartzCore 0x0459f380 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
24 QuartzCore 0x04507156 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
25 QuartzCore 0x045084e1 _ZN2CA11Transaction6commitEv + 393
26 QuartzCore 0x04508bb4 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
27 CoreFoundation 0x01a9753e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
28 CoreFoundation 0x01a9748f __CFRunLoopDoObservers + 399
29 CoreFoundation 0x01a753b4 __CFRunLoopRun + 1076
30 CoreFoundation 0x01a74b33 CFRunLoopRunSpecific + 467
31 CoreFoundation 0x01a7494b CFRunLoopRunInMode + 123
32 GraphicsServices 0x02ebc9d7 GSEventRunModal + 192
33 GraphicsServices 0x02ebc7fe GSEventRun + 104
34 UIKit 0x005c594b UIApplicationMain + 1225
35 FoodForTeeth 0x0001c42d main + 141
36 libdyld.dylib 0x02b5e701 start + 1
37 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
SecondViewController.swift
import UIkit
import CoreData
#objc(SecondViewController) class SecondViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var txtTask: UITextField!
#IBOutlet var txtDesc: UITextField!
#IBOutlet var date: UIDatePicker!
#IBOutlet var dateDisplayLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
configureDatePicker()
}
func configureDatePicker() {
date.addTarget(self, action: "updateDatePickerLabel", forControlEvents: .ValueChanged)
updateDatePickerLabel()
}
func updateDatePickerLabel() {
dateDisplayLabel.text = dateFormatter.stringFromDate(date.date)
}
#lazy var dateFormatter: NSDateFormatter = {
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = .ShortStyle
return dateFormatter
}()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//Events
#IBAction func btnAddTask_Click(sender: UIButton){
let appDel: foodforteethAppDelegate = UIApplication.sharedApplication().delegate as foodforteethAppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
let ent = NSEntityDescription.entityForName("Food", inManagedObjectContext: context)
var newFood = food(entity: ent, insertIntoManagedObjectContext: context)
newFood.foodname = txtTask.text
newFood.date = dateFormatter.stringFromDate(date.date)
context.save(nil)
/*
taskMgr.addTask(txtTask.text, desc: dateFormatter.stringFromDate(date.date));
self.view.endEditing(true)
txtTask.text = ""
//txtDesc.text = ""
//self.tabBarController.selectedIndex = 0;*/
self.navigationController.popViewControllerAnimated(true)
}
//iOS touch functions
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!){
self.view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField!) -> Bool {
textField.resignFirstResponder();
return true
}
}
You need to read https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
To import Swift code into Objective-C from the same target
Import the Swift code from that target into any Objective-C .m file
within that target using this syntax, and substituting the appropriate
name:
#import "ProductModuleName-Swift.h"
Any Swift files in your target will be visible in Objective-C .m files containing this import
statement. For information on using Swift from Objective-C code, see
Using Swift from Objective-C.
edit:
By adding QCAnnonce* a = [[QCAnnonce alloc] init];In my code somewhere before the function call, I solved the problem, so I guess that I "introduced the class to the runtime". But I have now a warning saying that "a" is unused, so is there a runtime function I can use to "introduce the class to the runtime"?
I am trying to create a client-server application. The objects are archived and unarchived for transmission using NSKeyed(Un)Archiver. Most of my objects are transmitted without any problem, but one of them raise an NSInvalidUnarchiveOperationException.
The exception is called before the breakpoint I placed in initWithCoder:.
I have tried to archive/unarchive before sending and this works well, so it shouldn't be an issue with initWithCoder.
I have tried to create a client in my server app (not in a separate app as my client) and he can decode the object. I can't see any difference between my client and this new client except that they are not in the same app.
The best guess I have is this part of the apple doc:
The delegate may, for example, load some code to introduce the class
to the runtime and return the class, or substitute a different class
object. If the delegate returns nil, unarchiving aborts and the method
raises an NSInvalidUnarchiveOperationException.
But I have no idea what "introduce the class to the runtime" means.
Here are this object methods for encoding/decoding:
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
a_listeAnnonces = [aDecoder decodeObjectForKey:#"Cartes"];
a_points = [aDecoder decodeIntForKey:#"Points"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:a_listeAnnonces forKey:#"Cartes"];
[aCoder encodeInt:a_points forKey:#"Points"];
}
Here is the exception message:
2014-06-04 11:27:34.681 myApp[3693:303] *** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (QCAnnonce)
2014-06-04 11:27:34.794 myApp[3693:303] (
0 CoreFoundation 0x00007fff8937a25c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8e898e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8937a10c +[NSException raise:format:] + 204
3 Foundation 0x00007fff8a8acdd9 _decodeObjectBinary + 2349
4 Foundation 0x00007fff8a8ac34d _decodeObject + 288
5 Foundation 0x00007fff8a8d15a5 +[NSKeyedUnarchiver unarchiveObjectWithData:] + 92
6 myApp 0x000000010001365f -[QNProtocolWrap performMethod:withArgumentDatas:onObject:] + 543
7 myApp 0x000000010001261b -[QNConnection methodCall:withArguments:] + 251
8 myApp 0x0000000100012b23 -[QNConnection connectionBaseDidRecieveNewData:] + 211
9 myApp 0x0000000100012b8b -[QNConnection connectionBaseDidRecieveNewData:] + 315
10 myApp 0x000000010000e38c -[QNConnectionBase readInput] + 204
11 myApp 0x000000010000e591 -[QNConnectionBase stream:handleEvent:] + 449
12 CoreFoundation 0x00007fff892ebc81 _signalEventSync + 385
13 CoreFoundation 0x00007fff892ebac8 _cfstream_solo_signalEventSync + 328
14 CoreFoundation 0x00007fff892eb93f _CFStreamSignalEvent + 623
15 CFNetwork 0x00007fff81e4401a _ZN29CoreReadStreamCFStreamSupport19coreStreamReadEventEP16__CoreReadStreamm + 102
16 CFNetwork 0x00007fff81e43f89 _ZN20CoreReadStreamClient25coreStreamEventsAvailableEm + 53
17 CFNetwork 0x00007fff81f77a65 _ZN14CoreStreamBase14_callClientNowEP16CoreStreamClient + 53
18 CFNetwork 0x00007fff81e43ca9 _ZN14CoreStreamBase34_streamSetEventAndScheduleDeliveryEmh + 183
19 CFNetwork 0x00007fff81e43a32 _ZN12SocketStream40dispatchSignalFromSocketCallbackUnlockedEP24SocketStreamSignalHolder + 74
20 CFNetwork 0x00007fff81e43160 _ZN12SocketStream14socketCallbackEP10__CFSocketmPK8__CFDataPKv + 206
21 CFNetwork 0x00007fff81e43062 _ZN12SocketStream22_SocketCallBack_streamEP10__CFSocketmPK8__CFDataPKvPv + 64
22 CoreFoundation 0x00007fff892eb107 __CFSocketPerformV0 + 855
23 CoreFoundation 0x00007fff892ab661 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
24 CoreFoundation 0x00007fff8929cd12 __CFRunLoopDoSources0 + 242
25 CoreFoundation 0x00007fff8929c49f __CFRunLoopRun + 831
26 CoreFoundation 0x00007fff8929bf25 CFRunLoopRunSpecific + 309
27 HIToolbox 0x00007fff89726a0d RunCurrentEventLoopInMode + 226
28 HIToolbox 0x00007fff897267b7 ReceiveNextEventCommon + 479
29 HIToolbox 0x00007fff897265bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
30 AppKit 0x00007fff82a9526e _DPSNextEvent + 1434
31 AppKit 0x00007fff82a948bb -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
32 AppKit 0x00007fff82a889bc -[NSApplication run] + 553
33 AppKit 0x00007fff82a737a3 NSApplicationMain + 940
34 myApp 0x0000000100001262 main + 34
35 myApp 0x0000000100001234 start + 52
36 ??? 0x0000000000000003 0x0 + 3
)
It seems that Class is not loaded to runtime at the moment when you are trying to decode it by NSKeyedArchiver.
If it's not loaded, NSKeyedArchiver just can't find class QCAnnounce. (And that's why it can't decode it)
To check this, you may look in the + (void)load method of NSObject protocol.
The runtime sends this message once per a class right after the Class is loaded into process's address space.
For classes that are part of the program's executable file, the runtime sends the load message very early in the process's lifetime. For classes that are in a shared (dynamically-loaded) library, the runtime sends the load message just after the shared library is loaded into the process's address space.
You can check this by overloading +(void)load method and setting breakpoint there and see if it's have been loaded to runtime before you are calling unarchive.
+ (void)load {
NSLog(#"%# loaded!", self);
}
Your fix [[QCAnnounce alloc] init] works because when Runtime is trying to send first message to a class, it needs to call +(void)initialize to that class and by the time you receive initialize, class in your process should have already received load.
The problem here is that the runtime didn't load all the class present in my static library. As I had no direct call to that class (only id), it was never loaded.
I fixed it by adding -objC in "other linker flags" in the build settings.
Some informations about why this was a good idea were found in this Technical Q&A:
-objC causes the linker to load every object file in the library that defines an Objective-C class or category
There exists two others flags (same Q&A):
-all_load forces the linker to load all object files from every archive it sees, even those without Objective-C code. -force_load is available in Xcode 3.2 and later. It allows finer grain control of archive loading. Each -force_load option must be followed by a path to an archive, and every object file in that archive will be loaded.
I'm experiencing a crash in TyphoonComponentFactory.m when trying to instantiate an object - this line crashes with EXC_BAD_ACCESS:
279:[pool setObject:instance forKey:definition.key];
Or sometimes this one:
276:id instance = [pool objectForKey:definition.key];
All the variables - pool, instance, definition, look right at the time it crashes, in the debugger. Earlier in the program's execution (but not much earlier, i.e. the same runloop) I've set up my TyphoonComponentFactory and made it the default factory. Is there anything that could be causing this? I had a vague theory that the factory is created too late for the callers but... pretty weak.
Typhoon version 1.8.2. Here's the assembly:
#import "EndpointQueueAssembly.h"
#import "EndpointQueue.h"
#import "URLStorage.h"
#import "EndpointHTTPMethods.h"
#import "EndpointURLStrings.h"
#import "HTTPRequestOperationFactory.h"
#import "Services.h"
#import "ChatImageCheck.h"
#implementation EndpointQueueAssembly
-(id)endpointQueue
{
return [TyphoonDefinition withClass: [EndpointQueue class] properties:^(TyphoonDefinition *definition) {
[definition setScope:TyphoonScopeSingleton];
}];
}
-(id)urlStorage
{
return [TyphoonDefinition withClass: [URLStorage class]];
}
-(id)endpointHTTPMethods
{
return [TyphoonDefinition withClass: [EndpointHTTPMethods class]];
}
-(id)chatImageCheck
{
return [TyphoonDefinition withClass: [ChatImageCheck class]];
}
-(id)endpointURLStrings
{
return [TyphoonDefinition withClass: [EndpointURLStrings class] properties:^(TyphoonDefinition *definition) {
[definition injectProperty:#selector(urlStorage)];
}];
}
-(id)httpRequestOperationFactory
{
return [TyphoonDefinition withClass: [HTTPRequestOperationFactory class] properties:^(TyphoonDefinition* definition) {
[definition injectProperty:#selector(endpointHTTPMethods)];
[definition injectProperty:#selector(endpointURLStrings)];
}];
}
-(id)services
{
return [TyphoonDefinition withClass:[Services class] properties:^(TyphoonDefinition *definition) {
[definition setScope:TyphoonScopeSingleton];
}];
}
#end
Stack trace, for a crash on line 276:
Thread 65, Queue : NSOperationQueue 0x12434e90
#0 0x0473756b in -[__NSDictionaryM objectForKey:] ()
#1 0x0033c2dd in -[TyphoonComponentFactory sharedInstanceForDefinition:fromPool:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/TyphoonComponentFactory.m:276
#2 0x0033cb34 in -[TyphoonComponentFactory(TyphoonDefinitionRegisterer) objectForDefinition:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/TyphoonComponentFactory.m:315
#3 0x0033b01d in -[TyphoonComponentFactory componentForKey:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/TyphoonComponentFactory.m:151
#4 0x046a291d in __invoking___ ()
#5 0x046a282a in -[NSInvocation invoke] ()
#6 0x00335f69 in -[TyphoonBlockComponentFactory forwardInvocation:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/Block/TyphoonBlockComponentFactory.m:97
#7 0x0469e2da in ___forwarding___ ()
#8 0x0469e0ee in __forwarding_prep_0___ ()
#9 0x00022647 in +[CascadeItemRenderOperation isCurrentProfileWithDictionary:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Shared/CascadeItemRenderOperation.m:166
#10 0x00022d3b in +[CascadeItemRenderOperation countOfUnreadChatsWithDictionary:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Shared/CascadeItemRenderOperation.m:205
#11 0x00021c7c in +[CascadeItemRenderOperation renderWithDictionary:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Shared/CascadeItemRenderOperation.m:79
#12 0x001002b2 in -[GrindrGridViewPreRenderOperation main] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Grindr/GrindrGridViewPreRenderOperation.m:38
#13 0x02d0dc79 in -[__NSOperationInternal _start:] ()
#14 0x02c8a9c8 in -[NSOperation start] ()
#15 0x02d0ff44 in __NSOQSchedule_f ()
#16 0x04d164d0 in _dispatch_client_callout ()
#17 0x04d02fe0 in _dispatch_async_redirect_invoke ()
#18 0x04d164d0 in _dispatch_client_callout ()
#19 0x04d04eb7 in _dispatch_root_queue_drain ()
#20 0x04d05127 in _dispatch_worker_thread2 ()
#21 0x05045dab in _pthread_wqthread ()
Values of relevant objects:
self: TyphoonBlockComponentFactory with all relevant objects available in the registry.
definition: "Definition: class='AuthenticationDetails', key='authenticationDetails'"
pool: NSDictionary, 0 key/value pairs
instance: id, uninitialised pointer.
Here's the stack for the main thread at the time - also contains Typhoon references:
Thread 1, Queue : com.apple.main-thread
#0 0x05081802 in __psynch_mutexwait ()
#1 0x05047945 in _pthread_mutex_lock ()
#2 0x050477ac in pthread_mutex_lock ()
#3 0x0443a498 in objc_sync_enter ()
#4 0x0033c288 in -[TyphoonComponentFactory sharedInstanceForDefinition:fromPool:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/TyphoonComponentFactory.m:275
#5 0x0033cb34 in -[TyphoonComponentFactory(TyphoonDefinitionRegisterer) objectForDefinition:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/TyphoonComponentFactory.m:315
#6 0x0033b01d in -[TyphoonComponentFactory componentForKey:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/TyphoonComponentFactory.m:151
#7 0x046a291d in __invoking___ ()
#8 0x046a282a in -[NSInvocation invoke] ()
#9 0x00335f69 in -[TyphoonBlockComponentFactory forwardInvocation:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Pods/Typhoon/Source/Factory/Block/TyphoonBlockComponentFactory.m:97
#10 0x0469e2da in ___forwarding___ ()
#11 0x0469e0ee in __forwarding_prep_0___ ()
#12 0x000735e7 in -[Profile(Custom) isMe] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Utils/Profile+Custom.m:74
#13 0x0022a0eb in -[Profile(GrindrGridViewHash) grindrGridViewHash] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Shared/Profile+GrindrGridViewHash.m:84
#14 0x000ff3ed in -[GrindrGridViewPreRenderCache preRenderManagedObjectsForBackgroundExecution:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Grindr/GrindrGridViewPreRenderCache.m:105
#15 0x000ff174 in -[GrindrGridViewPreRenderCache preRenderManagedObjects:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Grindr/GrindrGridViewPreRenderCache.m:87
#16 0x00041c8f in -[GrindrGridView endUpdates] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Shared/GrindrGridView.m:825
#17 0x002343d2 in -[CascadeDataSource controllerDidChangeContent:] at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Grindr/CascadeDataSource.m:137
#18 0x0276e347 in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] ()
#19 0x02d0c049 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke ()
#20 0x04709f04 in __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ ()
#21 0x04661efb in _CFXNotificationPost ()
#22 0x02c45e41 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#23 0x02670a13 in -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] ()
#24 0x0270ffaf in -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] ()
#25 0x0266beb8 in -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] ()
#26 0x0266b649 in -[NSManagedObjectContext processPendingChanges] ()
#27 0x0269a4cc in -[NSManagedObjectContext(_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] ()
#28 0x02712a14 in __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke ()
#29 0x02694b81 in internalBlockToNSManagedObjectContextPerform ()
#30 0x04d164d0 in _dispatch_client_callout ()
#31 0x04d05439 in _dispatch_barrier_sync_f_slow_invoke ()
#32 0x04d164d0 in _dispatch_client_callout ()
#33 0x04d04726 in _dispatch_main_queue_callback_4CF ()
#34 0x0471343e in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#35 0x046545cb in __CFRunLoopRun ()
#36 0x046539d3 in CFRunLoopRunSpecific ()
#37 0x046537eb in CFRunLoopRunInMode ()
#38 0x053ee5ee in GSEventRunModal ()
#39 0x053ee42b in GSEventRun ()
#40 0x03513f9b in UIApplicationMain ()
#41 0x0000e704 in main at /Users/nicklocking/Documents/primus-ios/NBFIOSCore/Shared/main.m:18
Further update:
It seems like Typhoon is defaulting to TyphoonScopeObjectGraph, which is apparently not thread-safe. We switched all non-singletons to TyphoonScopePrototype, and we now experience crashes in TyphoonCallStack -pop, in line 59, [_storage removeLastObject]. Seems to be an exception of some sort but the debugger doesn't spit anything useful out.
Cannot comment on your post (haven't enough reputation):
Yes, if you create components from different threads - it can be reason of crashes. Typhoon is not threaded-safe now(we are using NSMutableArray, NSMutableDictionary which are not threaded-safe, during object creation).
You can fix it by wrapping Typhoon call into serial queue or synchronized statement.. Or we can do it inside Typhoon (but it will be Typhoon 2.0 feature - hard to maintain two versions at same time)
Update:
Typhoon 2.0 is now thread-safe.
Here's our solution, which seems to work pretty well:
#import "TyphoonComponentFactory+SwizzledObjectForDefinition.h"
#import "JRSwizzle.h"
#implementation TyphoonComponentFactory (SwizzledObjectForDefinition)
+ (void)swizzleMethods
{
SEL objectForDefinitionSelector = sel_registerName("objectForDefinition:");
[TyphoonComponentFactory jr_swizzleMethod: objectForDefinitionSelector
withMethod: #selector(swizzledObjectForDefinition:)
error: nil];
}
// Synchronize objectForDefinition
- (id)swizzledObjectForDefinition:(TyphoonDefinition *)definition
{
#synchronized(self) {
return [self swizzledObjectForDefinition:definition];
}
}
#end
We also declare all scopes as either Singleton or Prototype.