My project in cocos2dv3 is throwing ARC Sematic Issue
Multiple methods named 'setRotation:' found with mismatched result, parameter type or attributes
while archiving(release mode). It runs fine while deploying to simulator/device (debug mode).
In release mode compiler gets confused between the implementation of rotation in UIRotationGestureRecognizer and CCNode.
When I got the error in CCBAnimationManager.m , I typecasted the object calling the selector setRotation to (CCNode*) but then the error crept up in CCActionInterval. I'm hoping there is a better solution than typecasting everywhere in cocos2d library.
What am i doing wrong?
Thankyou for your time.
EDIT
#interface CCAction : NSObject <NSCopying> {
id __unsafe_unretained _originalTarget;
id __unsafe_unretained _target;
NSInteger _tag;
}
#property (nonatomic,readonly,unsafe_unretained) id target;
#property (nonatomic,readonly,unsafe_unretained) id originalTarget;
#property (nonatomic,readwrite,assign) NSInteger tag;
in
CCAction.m
#synthesize tag = _tag, target = _target, originalTarget = _originalTarget;
-(void) startWithTarget:(id)aTarget
{
_originalTarget = _target = aTarget;
}
-(void) startWithTarget:(id)aTarget
{
_originalTarget = _target = aTarget;
}
Class Hierarchy
#interface CCActionFiniteTime : CCAction <NSCopying>
#interface CCActionInterval: CCActionFiniteTime <NSCopying>
#interface CCBRotateTo : CCActionInterval <NSCopying>
CCBRotateTo.m {
-(void) startWithTarget:(CCNode *)aTarget
{
[super startWithTarget:aTarget];
startAngle_ = [self.target rotation];
diffAngle_ = dstAngle_ - startAngle_;
}
-(void) update: (CCTime) t
{
[self.target setRotation: startAngle_ + diffAngle_ * t];
}
}
This problem gave me a big headache. Though I've upgraded cocos2d to v2.2 version for my old project (too complex to update to v3), I still got this warning. And any animation I created use rotation in the SpriteBuilder does act oddly, as I described here:
Rotation animation issue on iPhone5S with cocos2d 2.0
Finally I used type casting to solve it as following in CCBAnimationManager.m
#implementation CCBRotateTo
-(void)startWithTarget:(CCNode *)aTarget
{
[super startWithTarget:aTarget];
starAngle_ = [(CCNode *)self.target rotation];
diffAngle_ = dstAngle_ - startAngle_;
}
-(void)update:(ccTime)t
{
[(CCNode *)self.target setRotation: startAngle_ + diffAngle_ * t];
}
With this change, now I can support arm64 too.
update your cocos2dv3 to latest (RC4 for now).
I was using Xcode 5.0 and cocos2dv3 RC1 with no problem.
But updating Xcode to 5.1 I had this problem.
So I updated the cocos2dv3 to RC4 and now it's working fine.
You can find cocos 2d latest versions from here.
Related
I have this in my .pch file:
#import "UIViewController+Loader.h"
The implementation for the category looks like this:
static char kUIViewControllerBaseViewKey;
#implementation UIViewController (Loader)
- (void)setLoader:(LoaderView *)loaderView {
objc_setAssociatedObject(self, &kUIViewControllerBaseViewKey, loaderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (LoaderView *)loader {
LoaderView *loaderView = (LoaderView *)objc_getAssociatedObject(self, &kUIViewControllerBaseViewKey);
if (!loaderView) {
loaderView = [[LoaderView alloc] initWithView:self.view];
[self.view addSubview:loaderView];
[self setLoader:loaderView];
}
return loaderView;
}
#end
The problem is that in any view controller when I do this:
[self.loaderView doSomething];
Xcode shows this error: Property 'loaderView' not found on object of type MyViewController
HOWEVER, the project compiles fine and the doSomething: method on loaderView works fine. How can I get Xcode to stop showing these errors?
After much head scratching, I found a build setting called "Increase Sharing of Precompiled Headers". Changing this to YES made the problem go away. After reading the description of what this does, I still don't understand why this fixes the problem. But it's fixed.
I inherited an xcode project whose author compiled with iOS 6.1. I understand apple has stopped accepting projects built using iOS6 SDK, but for whatever reason I need to still be able to compile this for now using iOS 6.1
Anyways, everything worked fine until I needed to use the didTapMyLocationButtonForMapView: method (which notifies me when the use clicks on the my location button) that seems to be only available in the latest google maps SDK which is version 1.7.2 (I couldn't find the method in the gmaps sdk shipped with the project so i simply replaced the old library with the latest one).
However, after doing that I started getting this compilation error:
Undefined symbols for architecture i386: "_glMapBufferRange",
referenced from:
gmscore::renderer::BufferObject::MapBuffer() in GoogleMaps(BufferObject.o) ld: symbol(s) not found for architecture
i386 clang: error: linker command failed with exit code 1 (use -v to
see invocation)
Some claim on the web that this is because 1.7.2 is not compatible with iOS6. However, looking into the release notes of gmaps SDK.. I don't see any indication that 1.7.2 is not compatible with iOS 6 - notice how in the release note of version 1.5 they explicitly state
This release officially supports iOS 7, and requires iOS 6.0 or later
(iOS 5.1 is no longer supported).
but no such disclaimer is found for iOS 6.
any idea what's going on here?
i did wind up making google maps 1.7.2 working with iOS 7 (i don't remember exactly how, but that's the easy part.. usually when get these undefined architecture problems.. i solve them by taking out support for the arm 64 and setting valid architectures only to no) but then that didn't address my problem b/c the didTapMyLocationButtonForMapView: method was a dud: it didn't work in google maps 1.7.2 (ie when the user did tap the my location button.. nothing happened).
note: so if the only reason why you are here is to verify if google maps 1.7.2 works with iOS7 i can tell you that it indeed does work. The rest of the this answer is about how to fire a callback when the mylocationButton is clicked without using the google maps 1.7.2 didTapMyLocationButtonForMapView: method, regardless if you are using 1.7.2 or prior versions.
so i reverted back to the older version of google sdk (i had no other reason to upgrade).. and created my own code that fires when the user taps the my location button. this is how it works (in a nutshell.. i override the UIApplication sendEvent method that gets fired whenever a user touches the screen, and capture the events that happen at the same dimension as the myLocation button.. and then go from there)
first I created a custom UIApplication class:
in main.m:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, NSStringFromClass([TPMUApplication class]), NSStringFromClass([TPMUAppDelegate class]));
}
}
TPMUApplication.h
#interface TPMUApplication : UIApplication
// the view controller that has the google maps in it
#property (nonatomic, strong) TPMUVC *VC;
#end
TPMUApplication.m
#import "TPMUApplication.h"
#import "TPMUVC.h"
#implementation TPMUApplication
- (void)sendEvent:(UIEvent *)event
{
[super sendEvent:event];
UIView *touchReceipientView =((UITouch *)[event.allTouches anyObject]).view;
CGRect myLocationButtonFourchIncFrame = CGRectMake(256, 354, 64, 54);
CGRect myLocationButtonThreeHalfIncFrame = CGRectMake(256, 266, 64, 54);
if (CGRectEqualToRect(touchReceipientView.frame, myLocationButtonFourchIncFrame) ||
CGRectEqualToRect(touchReceipientView.frame, myLocationButtonThreeHalfIncFrame)) {
if (self.tVC.mapState != TPMUMapStateInMotionAsResultOfMyLocationButtonTap) {
self.VC.mapState = TPMUMapStateInMotionAsResultOfMyLocationButtonTap;
[self.VC didTapMyLocationButtonForMapView:self.VC.mapView];
}
}
}
#end
TPMUVC.h
#import <CoreLocation/CoreLocation.h>
#import <GoogleMaps/GoogleMaps.h>
typedef enum
{
TPMUMapStateIdle = 0,
TPMUMapStateInMotionAsResultOfUserGesture,
TPMUMapStateInMotionAsResultOfMyLocationButtonTap
} TPMUMapState;
#interface TPMUVC : TPMUBaseViewController<GMSMapViewDelegate>
#property (nonatomic, strong) GMSMapView *mapView;
#property (nonatomic, assign) TPMUMapState mapState;
- (BOOL)didTapMyLocationButtonForMapView:(GMSMapView *)mapView;
TPMUVC.m
#import "TPMUApplication.h"
#implementation TPMUVC
#synthesize mapView = mapView_;
#synthesize mapState = mapState_;
- (void)viewDidLoad
{
TPMUApplication *tpmuApp = (TPMUApplication *)[UIApplication sharedApplication];
tpmuApp.taxiRequestVC = self;
}
#pragma mark - GMSMapView delegate
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture
{
if (gesture) {
mapState_ = TPMUMapStateInMotionAsResultOfUserGesture;
}
}
- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position
{
if (mapState_ == TPMUMapStateInMotionAsResultOfUserGesture) {
mapState_ = TPMUMapStateIdle;
}
mapState_ = TPMUMapStateIdle;
mapCameraPosition_ = position;
DLog(#"map is now idle at position [lat: %f,long: %f] zoom: %f", position.target.latitude, position.target.longitude, position.zoom);
}
- (BOOL)didTapMyLocationButtonForMapView:(GMSMapView *)mapView {
return YES;
}
I'm currently bringing a legacy project up from iOS 5/6 to iOS 6/7.
Part of this project involves taking a picture using the GPUImage library, processing it with a crop filter, then optionally adding some saturation and blur effects. I am currently using version 0.1.2 installed via cocoa pods.
The problem I am having is that when I try to capture an image from the camera, I hit the following assert in GPUImageStillCamera.m line 254
if (CVPixelBufferGetPlaneCount(cameraFrame) > 0)
{
NSAssert(NO, #"Error: no downsampling for YUV input in the framework yet");
}
where cameraFrame is a CVImageBufferRef
I have reproduced the code where this is called and move it to another project, where it works perfectly.
Once I moved this reproduced class back into the main project, I was hitting the assert every time.
Things I've ruled out with my own debugging
64bit (it’s happening on both)
different lib version
initial object setup / code / usage
This has lead me to believe that perhaps it might be a project setting that I've over looked. Any help or even a pointer in the right direction would be very very welcome. I've spent a good 1-2 days on this now and am still entirely lost!
I've included the stripped down class below which shows the general use.
#import "ViewController.h"
#import "GPUImage.h"
#import "ImageViewController.h"
#interface ViewController ()
#property (nonatomic, strong) IBOutlet GPUImageView *gpuImageView;
#property (nonatomic, strong) GPUImageStillCamera *camera;
#property (nonatomic, strong) GPUImageCropFilter *cropFilter;
#end
#implementation ViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self setupCameraCapture];
}
- (void)setupCameraCapture
{
if (self.camera) {
return;
}
self.cropFilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0, 0, 1, 0.5625)];
if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]) {
self.camera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPresetPhoto cameraPosition:AVCaptureDevicePositionBack];
}
else {
self.camera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPresetPhoto cameraPosition:AVCaptureDevicePositionFront];
}
self.camera.outputImageOrientation = UIInterfaceOrientationPortrait;
NSError *error = nil;
[self.camera.inputCamera lockForConfiguration:&error];
[self.camera.inputCamera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
[self.camera.inputCamera setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
if ([self.camera.inputCamera respondsToSelector:#selector(isLowLightBoostSupported)]) {
BOOL isSupported = self.camera.inputCamera.isLowLightBoostSupported;
if (isSupported) {
[self.camera.inputCamera setAutomaticallyEnablesLowLightBoostWhenAvailable:YES];
}
}
[self.camera.inputCamera unlockForConfiguration];
[self.camera addTarget:self.cropFilter];
[self.cropFilter addTarget:self.gpuImageView];
[self.camera startCameraCapture];
}
- (IBAction)capturePressed:(id)sender
{
[self.camera capturePhotoAsImageProcessedUpToFilter:self.cropFilter withCompletionHandler:^(UIImage *image, NSError *error) {
// do something with the image here
}];
}
#end
The actual culprit was a swizzled method found by my colleague Marek. Hidden away in the depths of the old codebase. The above code works fine.
Lesson: if you really have to swizzle something, make sure you leave proper documentation for the future devs.
I'm developing an app that should detect a frequency of a certain sound. I based my app on Pitch Detector. I imported the files that are in the Pitch Detector example, then I fixed my code to accept this new classes. I post here my code to explain you my issue:
ViewController.h
#import <UIKit/UIKit.h>
#class RIOInterface;
#interface ViewController : UIViewController {
BOOL isListening;
float currentFrequency;
RIOInterface *rioRef; // HERE I'M GETTING ISSUE
}
- (IBAction)startListenWatermark:(UIButton *)sender;
#property(nonatomic, assign) RIOInterface *rioRef;
#property(nonatomic, assign) float currentFrequency;
#property(assign) BOOL isListening;
#pragma mark Listener Controls
- (void)startListener;
- (void)stopListener;
- (void)frequencyChangedWithValue:(float)newFrequency;
#end
ViewController.m
#synthesize isListening;
#synthesize rioRef;
#synthesize currentFrequency;
- (IBAction)startListenWatermark:(UIButton *)sender {
if (isListening) {
[self stopListener];
} else {
[self startListener];
}
isListening = !isListening;
}
- (void)startListener {
[rioRef startListening:self];
}
- (void)stopListener {
[rioRef stopListening];
}
- (void)frequencyChangedWithValue:(float)newFrequency {
NSLog(#"FREQUENCY: %f", newFrequency);
}
In the code you can see where's my issue and Xcode says: Existing instance variable 'rioRef' with assign attribute must be __unsafe_unretained. If I delete the row that give this errore the app doesn't calls the method [rioRef startListening:self]; and [rioRef stopListening];.
In the file RIOInterface.mm I'm getting another error in line 97 and Xcode suggested me to change it from:
RIOInterface* THIS = (RIOInterface *)inRefCon; --> RIOInterface* THIS = (RIOInterface *)CFBridgingRelease(inRefCon);
The it gives me this other error on the line 283:
callbackStruct.inputProcRefCon = self;
It says me this: Assigning to 'void' from incompatible type 'RIOInterface *const__strong', so I looked to the web and I found this solution:
callbackStruct.inputProcRefCon = (__bridge void*)self;
I'm not sure if it's right to do so or not, I hope you can help me to solve this issues, thank you in advice.
For the 2nd and the 3rd problem I solved by disabling the ARC for the file in which there are the code I provided above. For the first problem I solved by writing this code:
rioRef = [RIOInterface sharedInstance];
I've been writing a simple fahrenheit/celcius converter style app. It works fine in the simulator but when I test the app on my iPhone 4, it is very jerky and slow to update as I move the slider back and forth.
My main view controller looks like this (removed some junk):
#import "MLViewController.h"
#import "MLGradeModel.h"
#import "MLGrade.h"
#interface MLViewController ()
#property (nonatomic, strong) MLGradeModel *gradeModel;
#end
#implementation MLViewController
#synthesize displayLeft = _displayLeft;
#synthesize displayRight = _displayRight;
#synthesize gradeModel = _gradeModel;
#synthesize buttonLeft = _buttonLeft;
#synthesize buttonRight = _buttonRight;
- (IBAction)dragEnter:(UISlider*)sender {
[self sliderUpdate: sender];
}
- (IBAction)sliderInput:(UISlider*)sender {
[self sliderUpdate:sender];
}
- (IBAction) sliderValueChanged:(UISlider *)sender {
[self sliderUpdate:sender];
}
-(IBAction)sliderUpdate:(UISlider*)sender
{
UILabel *myDisplayLeft = self.displayLeft;
UILabel *myDisplayRight = self.displayRight;
float sliderValue = [sender value];
int pos = sliderValue*1000/CONVERSION_SCALE;
NSString *strLeft = [self.gradeModel readGradeFromLeftAtPos:pos];
NSString *strRight = [self.gradeModel readGradeFromRightAtPos:pos];
[myDisplayLeft setText:strLeft];
[myDisplayRight setText:strRight];
// try to redraw, maybe less jerky?
[self.view setNeedsDisplay];
}
-(int) getSliderValue
{
float initialValue = [self.sliderInput value];
return initialValue * 100;
}
- (void)viewDidLoad
{
[super viewDidLoad];
MLGradeModel *model = [MLGradeModel sharedMLGradeModel];
self.GradeModel = model;
}
#end
gradeModel is an NSMutableArray of NSMutableArrays, who contain NSString values. As the slider is dragged, the corresponding position in the arrays should be read. Whose values should then be set to the UILabels.
I thought it should be the most simple thing. Outlets and actions for the UISlider have been dragged in the storyboard.
Edit: Also, when I run the app on the phone, the logs show that the slider input is taken, but the window is not updated at speed "so to say". For example, then I move the slider form left to right the event shows up in the log but the labels are redrawn with 0.5 s delay.
Edit: [self.view setNeedsDisplay]; was added as a test to force a redraw. The program works equally bad/slow when that line is commented away.
Edit: It works equally bad when I change sliderUpdate to:
-(IBAction)sliderUpdate:(UISlider*)sender
{
float sliderValue = [sender value];
int pos = sliderValue*10;
NSString *strFromInt = [NSString stringWithFormat:#"%d",pos];
[self.displayLeft setText:strFromInt];
[self.displayRight setText:strFromInt];
}
-Have I not hooked up all events from the UISlider? I have only set valueChanged to to my viewController's sliderInput (which calls sliderUpdate).
I have this same delay issue with UISlider on an iPhone 4 with my app now i have started targeting iOS 7
On iOS 6 my sliders worked perfectly on an iPhone 4.
The same app works smoothly on a 4s and an ipad mini that i have here
EDIT
What I've just discovered is that in my app there was big difference in the UISlider performance on iPhone 4 under iOS 7 when I built for debug and built for release.
I had a bunch of logging going on in the slider - using DLog instead of NSLog - DLog is a macro that expands to an NSlog on running in debug mode and a no-op in release mode. so it appears that the logging was causing the lagging.
Check to see if you have logging going on in there and either comment them out or, if you are using Dlog, try changing the scheme to release and see if this solves your issue and see if that makes a difference,
To change to release look in Xcode menu Product-Scheme-Edit Scheme)
Made the world of difference to me.
Bit of a relief that !