Attempting to segue from Objective-C to Swift VC - ios

i'm trying to segue from objective-c to swift.
However when I try this using the object below I receive the following error
I don't know what i'm doing wrong, i've setup the segue on the storyboard and assigned it to the same ID, created the prepare function and the perform.
- (void)renderer:(id<SCNSceneRenderer>)renderer willRenderScene:(SCNScene *)scene atTime:(NSTimeInterval)time {
// Look for trackables, and draw on each found one.
size_t trackableCount = trackableIds.size();
for (size_t i = 0; i < trackableCount; i++) {
// NSLog(#"this is the variable value: %d", trackableIds[i]);
// Find the trackable for the given trackable ID.
ARTrackable *trackable = arController->findTrackable(trackableIds[i]);
// SCNCamera *camera = self.cameraNode.camera;
SCNNode *trackableNode = self.trackableNodes[i];
if (trackable->visible) {
if (trackableIds[i] == 0) {
NSLog(#"Starbucks");
[self performSegueWithIdentifier:#"brandSegue" sender:self];
} else if (trackableIds[i] == 1) {
NSLog(#"Dortios");
}
} else {
trackableNode.opacity = 0;
}
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"brandSegue"]) {
JSONViewController *destViewController = segue.destinationViewController;
}
}
EDIT - ERROR MESSAGE
2017-11-09 16:57:05.232992+0000 MyARApp[2573:1099927] *** Assertion failure in -[UIApplication _cachedSystemAnimationFenceCreatingIfNecessary:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3698.21.8/UIApplication.m:1707
2017-11-09 16:57:05.233169+0000 MyARApp[2573:1099927] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'accessing _cachedSystemAnimationFence requires the main thread'
*** First throw call stack:
(0x186f51d04 0x1861a0528 0x186f51bd8 0x1878e1c24 0x1905e9c4c 0x19064646c 0x190432338 0x19038fe5c 0x1903fb6a8 0x190470bf0 0x1906ffb00 0x190701434 0x190703cd8 0x19070420c 0x190703c28 0x190467ab4 0x190707ae4 0x190b38854 0x190ca6b30 0x190ca69d4 0x1906f7e18 0x1020a27cc 0x19a66c610 0x19a725a84 0x19a723e00 0x19a724d1c 0x19a5a0cc4 0x19a6717ac 0x19a671b14 0x19a671f8c 0x19a71a67c 0x19a5d24a0 0x19a6e1c90 0x1035b949c 0x1035b945c 0x1035c8110 0x1035bc9a4 0x1035c9104 0x1035d0100 0x186b7afd0 0x186b7ac20)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

After discussion in Chat and fixing various issues, I'll take them one by one:
> *** Assertion failure in -[UIApplication _cachedSystemAnimationFenceCreatingIfNecessary:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3698.21.8/UIApplication.m:1707
> *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'accessing _cachedSystemAnimationFence requires the main thread'
That's the first issue causing a crash. This is talking about an internal method of CocoaTouch needed to be called in main thread.
The issue lies on your performSegueWithIdentifier:sender:. All UI related calls have to be done in main thread.
To fix it:
dispatch_async(dispatch_get_main_queue(), ^(){
[self performSegueWithIdentifier:#"brandSegue" sender:self];
});
Fixing this revealed a second issue:
it segues but it trigger twice, do you know why this may happen?
You are doing this:
for (size_t i = 0; i < trackableCount; i++)
{
if (somethingTest)
{
[self performSegueWithIdentifier:#"brandSegue" sender:self];
}
}
Who said that in your for loop you don't valid multiple times somethingTest?
To fix it (I'm talking about the logic, I didn't do the dispatch_async(dispatch_get_main_queue(){()} part to avoid adding noise to the algorithm).
//Declare a var before the for loop
BOOL seguedNeedsToBeDone = FALSE;
for (size_t i = 0; i < trackableCount; i++)
{
if (somethingTest)
{
seguedNeedsToBeDone = TRUE;
}
}
//Perform the segue after the for loop if needed
if (seguedNeedsToBeDone)
{
[self performSegueWithIdentifier:#"brandSegue" sender:self];
}
Next issue, passing data to the Destination ViewController:
JSONViewController *destViewController = segue.destinationViewController;
destViewController.brand = #"something";
You are mixing Swift & Objective-C, since XCode was complaining about not knowing brand being a property of JSONViewController object, you needed to add #objc before the declaration of the var. More detailed answer can be found here.
Finally, a tip to pass the data of you for loop is using the sender (it's faster in term of coding than creating another var, etc.):
//Calling the performSegue with custom value to pass
[self performSegueWithIdentifier:#"brandSegue" sender:someVarToSend];
//Passing the custom value
destViewController.brand = someVarToSend;

I guess the more safe way is to use navigationController?.pushViewController(_:animated:), instead of using segues.

Related

Is it possible to intercept all method class on any UIViewController subclass

Let's say I wanted to be able to intercept any method calls to a UIViewController subclass.
First of all, I swizzle the +(instancetype)alloc method and I check if the current instance isKindOfClass:[UIViewController class]. If it is I go ahead and instantiate my proxy with the target.
///swizzled Alloc
+ (instancetype)monitoredAlloc {
id obj = [self monitoredAlloc];
if([obj isKindOfClass:[UIViewController class]]) {
id proxy = [PMGProxy proxyWithObject:obj];
return proxy;
}
return [self monitoredAlloc];
}
---------------------------------------
/// Proxy class
#implementation PMGProxy
+ (instancetype)proxyWithObject:(id)obj {
PMGProxy *proxy = [self alloc];
proxy.obj = obj;
return proxy;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
[invocation setTarget:_obj];
[invocation invoke];
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.obj methodSignatureForSelector:sel];
}
- (Class)class {
return [self.obj class];
}
The problem is that I get crashes, so I would expect the implementation of my Proxy is wrong... What am I doing wrong?
Here is the exception:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'This coder requires that replaced objects be returned from initWithCoder:'
From the error it seems that the coder is only happy to accept a different class returned from initCoder: rather than earlier in the process at the alloc stage.
Might be worth looking up NSSecureCoding for more detail on the whole process.
While you’re at it, take a look at the stack track that resulted in your exception, it will give you a bit more perspective on just how deep this rabbit hole goes.

Getting "unrecognized selector sent to instance" error message on 1 of 4 background image loads within same code?

I have created 4 buttons named cell1, cell2 cell3 and cell4
I am attempting to set the background image in the following for loop.
Cells 1, 2 and 4 load successfully with the background image.
I received the following message for cell3.
All cells were created the same, the tag for each button was set 1, 2, 3 and 4.
I am a loss as to why cell3 (button) does not load. I have reviewed similar previously answered question on this topic but am drawing a blank.
Here is the code that is failing:
for (int i = 1; i <= 4; ++i) {
UIButton *cellIndex = (UIButton *)([self.view viewWithTag:i]);
NSLog(#"==> viewDidLoad cellIndex1 = (%i)", cellIndex.tag);
[cellIndex setBackgroundImage:[UIImage imageNamed:#"L0background.png"] forState:UIControlStateNormal];
}
Here is the results for the background load:
2013-08-30 09:50:07.898 match[863:11f03] ==> viewDidLoad cellIndex1 = (1)
2013-08-30 09:50:07.899 match[863:11f03] ==> viewDidLoad cellIndex1 = (2)
2013-08-30 09:50:07.899 match[863:11f03] ==> viewDidLoad cellIndex1 = (3)
2013-08-30 09:50:07.900 match[863:11f03] -[UIView setBackgroundImage:forState:]: unrecognized selector sent to instance 0x7d68230
2013-08-30 09:50:07.901 match[863:11f03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setBackgroundImage:forState:]: unrecognized selector sent to instance 0x7d68230'
*** First throw call stack:
(0x1912012 0x1695e7e 0x199d4bd 0x1901bbc 0x190194e 0x27bf 0x6bb1c7 0x6bb232 0x60a3d5 0x60a76f 0x60a905 0x613917 0x22f5 0x5d7157 0x5d7747 0x5d894b 0x5e9cb5 0x5eabeb 0x5dc698 0x277ddf9 0x277dad0 0x1887bf5 0x1887962 0x18b8bb6 0x18b7f44 0x18b7e1b 0x5d817a 0x5d9ffc 0x202d 0x1f55 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Your cellIndex is declared inside the for loop. Its local to the for loop. You are trying to set a background image outside the for loop where it has no knowledge of cellIndex object. Have you declared a cellIndex object outside that for loop?
If not, then you will have to set the background image inside your for loop.
The problem is clear: [self.view viewWithTag:i]) is returning an UIView instead of an UIButton when i is 3.
You can verify that yourself by adding NSLog(#"Returned view: %#", cellIndex) just below that line. This log will also show which view is returned. You can then use that information to identify the culprit. I suspect that there's another view in the view hierarchy with 3 as tag. Double-check your XIBs/Storyboards to make sure the only view that has 3 as its tag is your button.
Like the others have said, UIView does not respond to the method in question. The object at index 4 is not a UIButton.
To help guard against this crash, do this:
UIButton *buttonObject;
for (int i = 1; i <= 4; ++i) {
id cellIndex = [self.view viewWithTag:i];
if ([cellIndex isKindOfClass:[UIButton class]]) {
buttonObject = (UIButton *)cellIndex;
NSLog(#"==> viewDidLoad cellIndex1 = (%i)", cellIndex.tag);
[buttonObject setBackgroundImage:[UIImage imageNamed:#"L0background.png"] forState:UIControlStateNormal];
} else {
NSLog(#"Not a button, returned %#",[cellIndex class]);
}
}

When i click an item in my collection view i got this error

I have a collectionview but when i tried to click the image the it showing this error ? The whole application is a tabbar application ,so all other tabs are working . except the last tab images.
iam taking images from plist for displaying it into collectionview
this is error
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI
objectAtIndex:]: index 0 beyond bounds for empty array'*** First throw call stack: (0x1e92012
0x1969e7e 0x1e47b44 0x58b91 0x56686 0x137cf 0x98f1c7 0x98f232 0x98f4da 0x9a68e5 0x9a69cb 0x9a6c76
`0x9a6d71 0x9a789b 0x9a7e93 0x9a7a88 0xd03e63 0xcf5b99 0xcf5c14 0xdaf5d9 0xdc1182 0xdc1394 0x197d705
0x9bb93c 0x9bb9ac 0x197d705 0x9bb93c 0x9bb9ac 0xb751d3 0x1e5aafe 0x1e5aa3d 0x1e387c2 0x1e37f44
0x1e37e1b 0x3c0f7e3 0x3c0f668 0x8adffc 0x287d 0x27a5) libc++abi.dylib: terminate called throwing an exception
This is the didselect method and preparesegue for passing that array to another viewcontroller
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"bookItem"]) {
NSDictionary *currentBook = [[_freeBooks objectForKey:#"freebook"] objectAtIndex:[[[self.collectionView indexPathsForSelectedItems] objectAtIndex:0] row]];
NSLog(#"%#", currentBook);
GMMDetailpage *detailpage = (GMMDetailpage *)[segue destinationViewController];
detailpage.bookDetails = currentBook;
NSLog(#"%#",detailpage.bookDetails);
}
}
The value of current book is printing and its fine.... but after this it executes some other system codes and then it shows exception .check image
You are doing two array accesses, so the error comes from the fact that one of the two arrays is empty.
The two arrays are
[self.collectionView indexPathsForSelectedItems]
and
[_freeBooks objectForKey:#"freebook"]
Check both the array independently and find out which one is the empty one.

Objective C - -[__NSCFString _isAncestorOfFirstResponder] Error

I'm trying to create this application, when you press on a tablecell you get shown the ViewController, and the variable get's set in the other view controller. Although i'm getting a few errors when i press the uitablecell.
Error:
2013-04-06 22:47:25.970 iFSX Guide[1069:907] Called
2013-04-06 22:47:26.009 iFSX Guide[1069:907] -[__NSCFString _isAncestorOfFirstResponder]: unrecognized selector sent to instance 0x1d562390
2013-04-06 22:47:26.016 iFSX Guide[1069:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString _isAncestorOfFirstResponder]: unrecognized selector sent to instance 0x1d562390'
*** First throw call stack:
(0x319b22a3 0x3964c97f 0x319b5e07 0x319b4531 0x3190bf68 0x33832beb 0x338a837f 0x338548fb 0x33a95619 0x338a79b9 0x338a5fe7 0x339c83ef 0xa22a5 0x3387c28d 0x338fef81 0x322c0277 0x319875df 0x31987291 0x31985f01 0x318f8ebd 0x318f8d49 0x354ba2eb 0x3380e301 0xa19d1 0x39a83b20)
libc++abi.dylib: terminate called throwing an exception
The code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)in dexPath{
NSLog(#"Called");
Aircraft = indexPath.row;
[self performSegueWithIdentifier:#"ToSections" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"ToSections"]){
AirplaneSections *sections = (AirplaneSections *)segue.destinationViewController;
sections.plane = Aircraft;
}
}
I've found out that it's an error on ViewDidLoad on the viewcontroller.
NSString *quickTemp = [NSString alloc];
switch (plane) {
case 0:
quickTemp = #"Boeing 737-800";
break;
default:
break;
}
TitleLabel.text = quickTemp;
*/
I'm doing something wrong there.
Are you using ARC? This sort of problem usually indicates there's a memory error somewhere. Basically, some code somewhere is trying to access an object that was already released. This makes everything go kaboom.
If you aren't using ARC, you should turn it on.
After that, the next thing you should do is run the static analyzer. Fix anything that comes up.
If that doesn't fix the problem, in Xcode, add a breakpoint that stops when an Objective-C exception is thrown. It should show you where exactly this problem is happening.
If that doesn't help, run your code under Instruments' and the Zombie tool. This will show you exactly where you tried to access memory that was already released.

use subclass of CCLayer for CCScrollLayer

I've created a custom class which is a subclass of CCLayer and trying to use it for CCScrollLayer
The way I do it is:
//Store the my layers to an NSMutableArray
for (AACustomClassLayer *cardLayer in levels) {
[layers addObject:cardLayer];
}
Under the hood of CCScrollLayer it crashes at:
- (void) updatePages
{
// Loop through the array and add the screens if needed.
int i = 0;
for (CCLayer *l in layers_)
{
l.anchorPoint = ccp(0,0);
l.contentSize = [CCDirector sharedDirector].winSize;
l.position = ccp( (i * (self.contentSize.width - self.pagesWidthOffset)), 0 );
if (!l.parent)
[self addChild:l];
i++;
}
}
The implementation for the AACustomClassLayer class (subclass of CCLayer) looks like:
-(id)initWithChapter:(AALevel *)level {
self = [super init];
if (self) {
self.isTouchEnabled = YES;
//Here I'm adding the CCSprite to my layer
}
return self;
}
UPDATE:
Crash log
2012-04-20 14:12:12.344 [15780:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setAnchorPoint:]: unrecognized selector sent to instance 0x884ab40'
*** First throw call stack:
(0x1a75022 0x200fcd6 0x1a76cbd 0x19dbed0 0x19dbcb2 0xd013f 0xcfe2b 0x102370 0x44c15 0xbe45f 0x8a94be 0x8aa274 0x8b9183 0x8b9c38 0x8ad634 0x282def5 0x1a49195 0x19adff2 0x19ac8da 0x19abd84 0x19abc9b 0x8a9c65 0x8ab626 0xbda06 0x22e5)
terminate called throwing an exception
I've found it!
for (AACustomClassLayer *cardLayer in levels) {
cardLayer = [[AACustomClassLayer node] autorelease];
[layers addObject:cardLayer];
}
You should add a conditional check in your for loop that determines if the object you are getting from enumeration is in fact a CCLayer. Your crash log states that the anchorPoint setter was not available on some object, presumably on an object in your layers_ array since that is the code you have posted that deals with anchorPoints.
Enumeration is convenient, but you are casing all objects to CCLayer when it is possible that one of them is not. I don't know where you are adding objects to layers_ but is it possible you are adding an object that is not actually a CCLayer ?

Resources