I tried to compile a tweak using theos, an amazing framework to create tweaks easily on many different platform. Here I am trying to show a settings icon every time I respring and slowly fade it out but it is failing to compile. I have all the needed headers and frameworks and am running a real Mac (Despite the name u see on my terminal :P) with the latest Xcode installed and a previous install of the Xcode 4.2. This is the tweak.xm:
#import <UIKit/UIKit2.h>
#import <objc/runtime.h>
#import <SpringBoard/SpringBoard.h>
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <substrate2.h>
#import <IOSurface/IOSurface.h>
#import <QuartzCore/QuartzCore2.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CaptainHook/CaptainHook.h>
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <AVFoundation/AVAudioPlayer.h>
#import <Celestial/Celestial.h>
#import <SpringBoardServices/SpringBoardServices.h>
#import <CoreFoundation/CFNotificationCenter.h>
#import <ChatKit/ChatKit.h>
%hook CKConversationListController
- (void)composeButtonClicked:(id)clicked {
}
%end
%hook SpringBoard
-(void)applicationDidFinishLaunching:(id)application {
NSArray *animationArray = [NSArray arrayWithObjects:[UIImage imageNamed:#"/Applications/Preferences.app/BlobIcon#2x.png"], nil];
[NSTimer scheduledTimerWithTimeInterval:.75 target:self selector:#selector(crossfade) userInfo:nil repeats:YES];
mainImageView.animationImages = animationArray;
mainImageView.animationDuration = 4.5; //mainImageView is instance of UIImageView
mainImageView.animationRepeatCount = 0;
[mainImageView startAnimating];
CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:#"contents"];
crossFade.autoreverses = YES;
crossFade.repeatCount = 1;
crossFade.duration = 1.0;
}
%new
- (void) crossfade {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; // user dependent transition acn be set here
mainImageView.alpha = !mainImageView.alpha;
[UIView commitAnimations];
}
%end
And the makefile looks like this:
include theos/makefiles/common.mk
export GO_EASY_ON_ME=1
TWEAK_NAME = Goofy
Goofy_FILES = Tweak.xm
Goofy_FRAMEWORKS = Foundation UIKit CoreGraphics ChatKit
Goofy_PRIVATE_FRAMEWORKS = ChatKit VoiceServices AppSupport
include $(THEOS_MAKE_PATH)/tweak.mk
I am keeping on getting
Making all for tweak Goofy...
Preprocessing Tweak.xm...
Compiling Tweak.xm...
Tweak.xm: In function ‘void _logos_method$_ungrouped$SpringBoard$applicationDidFinishLaunching$(SpringBoard*, objc_selector*, objc_object*)’:
Tweak.xm:32: error: ‘mainImageView’ was not declared in this scope
Tweak.xm: In function ‘void _logos_method$_ungrouped$SpringBoard$crossfade(SpringBoard*, objc_selector*)’:
Tweak.xm:53: error: ‘mainImageView’ was not declared in this scope
make[2]: *** [.theos/obj/Tweak.xm.o] Error 1
make[1]: *** [internal-library-all_] Error 2
make: *** [Goofy.all.tweak.variables] Error 2
Hackint0sh-HD:Goofy iHackerMe$
What am I missing here?
The problem is that mainImageView hasn't been declared as anything...
Just do UIImageView *mainImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"/Applications/Preferences.app/BlobIcon#2x.png"]];
Unless you're trying to move an object that is already on the lockscreen like say the clock, in that case you'd need to find out what the object is, include it in the file using #import and then animating it like you have already.
Related
I want to create a compass app that function exactly the same as current iphone ! Can somebody point me direction ,please? I am new at this !
How to create an Compass in iOS:
Step 1: Create a project (e.g. CompassExample) and include frameworks
#import <CoreLocation/CoreLocation.h>
#import <QuartzCore/QuartzCore.h>
ViewContoller.h Steps:
Step 2: In .h file, create Location Manager Object
CLLocationManager *locationManager;
<CLLocationManagerDelegate>
#property (nonatomic,retain) CLLocationManager *locationManager;
#synthesize locationManager;
IBOutlet UIImageView *compassImage;
Step 3: Dowload this Compass Image
ViewController.m Steps:
Step 4: In .m file’s viewDidLoad function, initialize the location manager.
locationManager=[[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.headingFilter = 1;
locationManager.delegate=self;
[locationManager startUpdatingHeading];
Step 5: In .m file, implement delegate function.
First, you need to convert degree (e.g 360) to radian (e.g 3.14=2PI).
Second, multiply -1 in order to rotate opposite direction that you twist your phone.
Third, apply rotation with core animation function. In this example, I’m rotating from the current value to the new value. The duration is 0.5 second as you see below.
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
// Convert Degree to Radian and move the needle
float oldRad = -manager.heading.trueHeading * M_PI / 180.0f;
float newRad = -newHeading.trueHeading * M_PI / 180.0f;
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"transform.rotation"];
theAnimation.fromValue = [NSNumber numberWithFloat:oldRad];
theAnimation.toValue=[NSNumber numberWithFloat:newRad];
theAnimation.duration = 0.5f;
[compassImage.layer addAnimation:theAnimation forKey:#"animateMyRotation"];
compassImage.transform = CGAffineTransformMakeRotation(newRad);
NSLog(#"%f (%f) => %f (%f)", manager.heading.trueHeading, oldRad, newHeading.trueHeading, newRad);
}
That’s it! Of course, you have to deploy the app on your device to check the direction.
Credit for this Code goes to kiichi, you can download the Project at Github Link
I think I've hit a roadblock again, here's the deal:
Undefined symbols for architecture i386:
"CreateRenderer1()", referenced from:
-[GLView initWithFrame:] in GLView.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried nearly all the suggestions that shown up in the auto search when you ask a question:
Adding these libraries to the 'Link Binary With Libraries' tab under 'Build Phases':
OpenGLES.framework
QuartzCore.framework
Adding all relevant files to the target/compiled sources
Renaming all relevant files with the .m extension to .mm
I'm trying to compile this on the iPhone 5.1 Simulator on Xcode 4.3.2, is there anything glaringly obvious that I'm missing? I have a feeling it's something in the settings but nothing I've tried seems to work =(
Edit:
GLView.h:
#import "IRenderingEngine.hpp"
#import <OpenGLES/EAGL.h>
#import <QuartzCore/QuartzCore.h>
#interface GLView : UIView {
EAGLContext* m_context;
IRenderingEngine* m_renderingEngine;
float m_timestamp;
}
- (void) drawView: (CADisplayLink*) displayLink;
- (void) didRotate: (NSNotification*) notification;
#end
GLView.mm:
#import <OpenGLES/EAGLDrawable.h>
#import "GLView.h"
#import "mach/mach_time.h"
#import <OpenGLES/ES2/gl.h> // <-- for GL_RENDERBUFFER only
#implementation GLView
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer;
eaglLayer.opaque = YES;
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!m_context || ![EAGLContext setCurrentContext:m_context]) {
[self release];
return nil;
}
m_renderingEngine = CreateRenderer1();
[m_context
renderbufferStorage:GL_RENDERBUFFER
fromDrawable: eaglLayer];
m_renderingEngine->Initialize(CGRectGetWidth(frame), CGRectGetHeight(frame));
[self drawView: nil];
m_timestamp = CACurrentMediaTime();
CADisplayLink* displayLink;
displayLink = [CADisplayLink displayLinkWithTarget:self
selector:#selector(drawView:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
return self;
}
- (void) didRotate: (NSNotification*) notification
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
m_renderingEngine->OnRotate((DeviceOrientation) orientation);
[self drawView: nil];
}
- (void) drawView: (CADisplayLink*) displayLink
{
if (displayLink != nil) {
float elapsedSeconds = displayLink.timestamp - m_timestamp;
m_timestamp = displayLink.timestamp;
m_renderingEngine->UpdateAnimation(elapsedSeconds);
}
m_renderingEngine->Render();
[m_context presentRenderbuffer:GL_RENDERBUFFER];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
IRenderingEngine.hpp
enum DeviceOrientation {
DeviceOrientationUnknown,
DeviceOrientationPortrait,
DeviceOrientationPortraitUpsideDown,
DeviceOrientationLandscapeLeft,
DeviceOrientationLandscapeRight,
DeviceOrientationFaceUp,
DeviceOrientationFaceDown,
};
// Creates an instance of the renderer and sets up various OpenGL state.
struct IRenderingEngine* CreateRenderer1();
// Interface to the OpenGL ES renderer; consumed by GLView.
struct IRenderingEngine {
virtual void Initialize(int width, int height) = 0;
virtual void Render() const = 0;
virtual void UpdateAnimation(float timeStep) = 0;
virtual void OnRotate(DeviceOrientation newOrientation) = 0;
virtual ~IRenderingEngine() {}
};
Your IRenderingEngine implementation isn't being found by the compiler. Either the implementation is missing or the files aren't added to the target correctly.
Although I fixed it, I never really understood how the files 'deleted' themselves, today, I found the answer:
If you rename any subfolders in the Finder manually, XCode will still point to the old path path, which is now invalid.
To fix this, I had right click on the invalid group folder, then, in the file inspected to the right, then click on an obscure tiny little box which lets me manually set the path again!
I define my own my own drawRect method and it is called on 4.2.1 (iOS) 5.0 (iOS) and 4.3.2 (Simulator) sucesfully. But it never called on 3.1.3 (iPhone 2g).
What reason could be for this?
P.S. Since i start write the question i think about my 3.1.3 device is jailbroken. Maybe it is root cause of this strange behaviour.
Upd: To reproduce issue i use next code:
#implementation UIView (MyOwnCategory)
- (void)drawRect:(CGRect)rect
{
const char * function = __FUNCTION__;
[NSException raise: #"hi!" format: #"%s", function];
}
#end
exception never happened on 3.1.3 even when i call [super drawRect: rect] explicitly
I wanted to write about Method Swizzling for a few weeks now, and #Kevin Ballard's comment finally made me do it (thank you for the inspiration, Kevin).
So here's a solution for your problem using method swizzling which should also work on iOS 3.x:
UIView+Border.h:
#import <Foundation/Foundation.h>
#interface UIView(Border)
#end
UIView+Border.m:
#import "UIView+Border.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
#implementation UIView(Border)
- (id)swizzled_initWithFrame:(CGRect)frame
{
// This is the confusing part (article explains this line).
id result = [self swizzled_initWithFrame:frame];
// Safe guard: do we have an UIView (or something that has a layer)?
if ([result respondsToSelector:#selector(layer)]) {
// Get layer for this view.
CALayer *layer = [result layer];
// Set border on layer.
layer.borderWidth = 2;
layer.borderColor = [[UIColor redColor] CGColor];
}
// Return the modified view.
return result;
}
- (id)swizzled_initWithCoder:(NSCoder *)aDecoder
{
// This is the confusing part (article explains this line).
id result = [self swizzled_initWithCoder:aDecoder];
// Safe guard: do we have an UIView (or something that has a layer)?
if ([result respondsToSelector:#selector(layer)]) {
// Get layer for this view.
CALayer *layer = [result layer];
// Set border on layer.
layer.borderWidth = 2;
layer.borderColor = [[UIColor blueColor] CGColor];
}
// Return the modified view.
return result;
}
+ (void)load
{
// The "+ load" method is called once, very early in the application life-cycle.
// It's called even before the "main" function is called. Beware: there's no
// autorelease pool at this point, so avoid Objective-C calls.
Method original, swizzle;
// Get the "- (id)initWithFrame:" method.
original = class_getInstanceMethod(self, #selector(initWithFrame:));
// Get the "- (id)swizzled_initWithFrame:" method.
swizzle = class_getInstanceMethod(self, #selector(swizzled_initWithFrame:));
// Swap their implementations.
method_exchangeImplementations(original, swizzle);
// Get the "- (id)initWithCoder:" method.
original = class_getInstanceMethod(self, #selector(initWithCoder:));
// Get the "- (id)swizzled_initWithCoder:" method.
swizzle = class_getInstanceMethod(self, #selector(swizzled_initWithCoder:));
// Swap their implementations.
method_exchangeImplementations(original, swizzle);
}
#end
I have an object called Shot which is a subclass of UIIMageView.
// Shot.h
#import <Foundation/Foundation.h>
#interface Shot : UIImageView {
CGPoint position;
}
- (void)SetShot:(CGPoint *)point;
#end
// Shot.m
#import "Shot.h"
#implementation Shot
- (void)SetShot:(CGPoint *)point;
{
position.x = point->x;
position.y = point->y;
}
#end
When I try to call the SetShot method, xcode gives me this warning:
method -SetShot not found(return type defaults to id)
Here is the call:
//CustomImageView.m
#import "CustomImageView.h"
#class Shot;
#implementation CustomImageView
-(id) initWithCoder:(NSCoder *)aDecoder
{
self.userInteractionEnabled = YES;
return self;
}
-(void) setInteraction
{
self.userInteractionEnabled = YES;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
Shot *shot;
[shot SetShot:point];
}
- (void)dealloc
{
[super dealloc];
}
#end
When I run the program, I get a fatal error when the method is called. Why is that?
There are three problems in your code. Firstly, you need to import Shot.h in your CustomImageView.m implementation file:
#import "Shot.h"
instead of simply forward-declaring the Shot class:
#class Shot;
When the compiler sees a forward declaration, it becomes aware of the existence of that class but doesn’t yet know its attributes, declared properties, or methods — in particular, it doesn’t know that Shot has a -SetPoint: instance method.
Secondly, you’re not creating an instance of Shot:
Shot *shot;
[shot SetShot:point];
This only declares that shot is a pointer to Shot but there’s no allocation/initialisation. You should create an object, i.e.:
Shot *shot = [[Shot alloc] init];
then use it:
[shot SetShot:point];
and, when you don’t need it any longer, release it:
[shot release];
Although it’s not clear what’s the benefit of creating a shot, setting its point, and then releasing it. Unless your code is a contrived example, you might want to rethink this behaviour.
Also, your -SetPoint: method has a pointer to CGPoint parameter but you’re passing a CGPoint value (i.e., not a pointer) argument:
// point is not a pointer!
CGPoint point = [touch locationInView:self];
Shot *shot;
[shot SetShot:point];
I suggest you drop the pointer altogether, i.e.:
- (void)SetShot:(CGPoint)point;
{
position = point;
}
and maybe use a declared property instead of a manually implemented setter method.
Do
#import "Shot.h"
instead of:
#class Shot;
You have not created an instance of Shot; you have only created a pointer with:
Shot *shot;
You must allocate and initialize it:
Shot *shot = [[Shot alloc] init];
At some point you must import the header file Shot.h as well.
I'm working on my first app and have a few questions on memory management.
First Question:
I'm working on an intro scene that looks like this
#import "Intro_Scene.h"
#import "Main_Menu.h"
#import "Label.h"
#implementation Intro_Scene
#synthesize logo,label;
-(id) init
{
self = [super init];
if(self != nil)
{
//Load logo image and set position
logo = [Sprite spriteWithFile:#"AVlogo_1.png"];
logo.position = ccp(-50, 0);
logo.scale = 1.8f;
[self addChild: logo];
//Creates 3 actions for the logo sprite
id action0 = [MoveTo actionWithDuration:0 position:ccp(160,270)];
id action1 = [FadeIn actionWithDuration:3];
id action2 = [FadeOut actionWithDuration:3];
//Logo runs the actions
[logo runAction: [Sequence actions:action0,action1, action2, nil]];
//Schedules the changeScene method to switch scenes to main menu within 6 seconds of loading.
[self schedule: #selector(changeScene) interval:6.0f];
//Creates a label and positions it, Alternative Visuals
label = [Label labelWithString:#"Alternative Visuals" fontName:#"Verdana" fontSize:22];
label.position = ccp(160, 120);
[self addChild:label];
}
return self;
}
//Method called after intro has run its actions, after 6 seconds it switches scenes.
-(void)changeScene
{
[self removeChild:logo cleanup:YES];
[self removeChild:label cleanup:YES];
Main_Menu *mainMenu = [Main_Menu node];
[[Director sharedDirector] replaceScene: mainMenu];
}
-(void)dealloc
{
[[TextureMgr sharedTextureMgr] removeUnusedTextures];
[label release];
[logo release];
[super dealloc];
}
#end
Have I released everything correctly, and avoided leaks? I ran it in instruments multiple times and it found no leaks and used about 2mb of memory, is that to much or the amount to be expected? Also does the dealloc method get called when the scene is replaced?
Question 2:
My main menu is set up like this
#import "Main_Menu.h"
#import "Sprite.h"
#import "cocos2d.h"
#implementation Main_Menu
#synthesize background, controlLayer;
-(id) init
{
self = [super init];
if(self != nil)
{
//Create the default background for main menu not including directional pad and highlight box
background = [Sprite spriteWithFile:#"Main_Menu_bg.png"];
background.position = ccp(160,240);
[self addChild:background];
//Adds the control later class to the main menu, control layer class displays and controls the directional pad and selector.
ControlLayer *layer = [[ControlLayer alloc] init];
self.controlLayer = layer;
[layer release];
[self addChild: controlLayer];
}
return self;
}
-(void) dealloc
{
[seld removeChild:background cleanup:YES];
[[TextureMgr sharedTextureMgr] removeUnusedTextures];
[background release];
[controlLayer release];
[super dealloc];
}
#end
Once again am I doing everything correctly? The layer ControlLayer I'm adding to this scene contains a directional pad sprite that the user uses to navigate the menu. In instruments It also confirms that their is no memory leaks, and it uses 4.79 mb of memory. Once again is that a reasonable amount? I will most likely switch to using AtlasSprite and AtlastSpriteManager to conserve memory.
I'm new to cocos2d, so if you see I'm doing anything wrong point it out! I'd rather fix bad habits in the early stages. And if you have any future tips for memory management please share.
Don't release logo, label, or background. You didn't alloc/copy/new/retain them, so you don't own them and must not release them.
I assume the controllerLayer property has the retain attribute? If not, you probably mean to do so.
In general I'd suggest two things going forward.
Read and understand the Cocoa Memory Management Fundamentals
Run the Clang analyzer on your code. This is available in Xcode 3.2 via Build->Build and Analyze. It will help detect these memory issues.
Also check out this SO question.