How to write correctly MSHook and MSHookIvar - ios

I'm doing a Tweak and i use Flex to edit some Obj-C but one of these i cant edit so, i think if i do a Tweak with MSHook can resolve this, BUT NO idk how to write correctly i'm new on this, i want to disable "shootCooldown" but idk if is posible, so this is my code on Tweak.x
#import <substrate.h>
#import <Foundation/Foundation.h>
#interface ControlsWidget : NSObject {
NSString *_shootCooldown;
}
#end
NSString *_shootCooldown;
%hook ControlsWiget
{
shootCooldown = MSHookIvar<BOOL>(self, "_someBOOL");
}
%end

Related

Unable to call swift function from objective-c in react-native

I'm fairly new to objective-c and swift so forgive me if this sounds dumb. Basically what I'm trying to do is *expose** a swift function to both react-native(so it can be used in JS) and to be used in objective-c. The issue I'm having is this dreaded "Duplicate interface definition for class...". I have researched and tried everything it seems but can not get rid of this error. I'm starting to wonder if is possible to do this. It seems so simple yet I just can't figure it out!
Here is my code:
AppDelegate.m
#import "MyApp-Swift.h"
#import "MyApp-Bridging-Header.h"
MyApp-Swift.h
#import "React/RCTEventEmitter.h"
#interface Counter : RCTEventEmitter
- (void)start;
- (void)stop;
#end
MyApp.swift
import Foundation
import UIKit
#objc(Counter)
class Counter: RCTEventEmitter {
#objc func start(){
}
#objc func end(){
}
}
MyApp-Bridging-Header.h
#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"
#interface RCT_EXTERN_MODULE(Counter, RCTEventEmitter)
RCT_EXTERN_METHOD(start);
RCT_EXTERN_METHOD(end);
#end
Inside AppDelegate.m didFinishLaunchingWithOptions() function
Counter* CounterInstance = [[Counter alloc] init];
[CounterInstance start];
If I remove the code from MyApp-Swift.h then I get the error "No visible #interface for..." BUT fixes the "Duplicate interface error" in MyApp-Bridging-Header.h. It seems like it contradicts each other!? How are you supposed to call a swift function from objective-c while also exposing the same function to JS?
I'm doing something similar in a project, and my setup looks like this:
Counter.m
#import "React/RCTBridgeModule.h"
#import "React/RCTViewManager.h"
#interface RCT_EXTERN_MODULE(Counter, NSObject)
RCT_EXTERN_METHOD(start)
RCT_EXTERN_METHOD(stop)
#end
Counter.swift
import React
#objc(Counter)
class Counter: RCTEventEmitter {
#objc func start() { /* ... */ }
#objc func stop() { /* ... */ }
}
and at the call site:
#import "YOURAPP-Swift.h" // the compiler creates this for you. don't edit!
-(void) foo {
Counter* cnt = [Counter new];
[cnt start];
}
(no other files used or modified. In particular, the bridging header isn't needed here)
I've found https://teabreak.e-spres-oh.com/swift-in-react-native-the-ultimate-guide-part-1-modules-9bb8d054db03 very helpful when I started doing this.

Why do I get Method definition for ... not found error after refactoring?

I have a very small class with an enum in the .h file, and that's it. I recently refactored the name of the .h file and for some reason the .m file names didn't refactor, so I had to change it manually. Now everything works as intended, but I suddenly get a warning on my #implementation in my .m file: Method definition for ... not found. Not sure why.
It looks like this in .m:
#import "TabTypeEnum.h"
#interface TabTypeEnum ()
#end
#implementation TabTypeEnum
- (void)viewDidLoad {
[super viewDidLoad];
}
#end
and in the .h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface TabTypeEnum : UIViewController
typedef enum {
MyTravels = 0,
Excursions,
Experiences,
Map,
Discover
} MyTabType;
- (void)myTabFunc: (MyTabType) myTab;
#end
NS_ASSUME_NONNULL_END
I didn't get the warning before, and all I did was change all the names to TabTypeEnum. I don't want to have the method implemented in the .m file. It's fine as it is.

iOS 7: Property not found on object of type

I have been following Apple's Start Developing iOS Apps Today guide and have run into a problem. I'm not a newbie developer but I am new to iOS development and I can't see why I'm going wrong.
I have a file called STRAddTodoViewController.h which contains the following
#import <UIKit/UIKit.h>
#import "STRTodo.h"
#interface STRAddTodoViewController : UIViewController
#property STRTodo *todoItem;
#end
And in my STRTodosViewController.m I have:
- (IBAction)unwindToList:(UIStoryboardSegue *)segue {
STRAddTodoViewController *addTodo = [segue sourceViewController];
STRTodo *item = addTodo.todoItem;
if (item != nil) {
[self.todos addObject:item];
[self.tableView reloadData];
}
}
And I'm getting an error of:
Property 'todoItem' not found on object of type 'STRAddTodoViewController *'
For some reason, my public variable in STRAddTodoViewController isn't getting picked up in my other controller and I can't for the life of me figure out why. Any clues?
EDIT: Massive apologies everyone, seems like I had two copies of STRAddTodoViewController in my project and it was reading the old one when it was building. Such a simple mistake and I feel like a massive idiot now, but thanks to everyone who helped me out.
Try to replace #import "STRTodo.h" by #class STRTodo; in your STRAddTodoViewController.h header file and add #import "STRTodo.h" in your STRAddTodoViewController.m implementation file.
Because if you already #import "STRTodo.h" and #import "STRAddTodoViewController.h" in your STRTodoViewController.h header file, compiler founds too much #import "STRTodo.h" and gets confused.
Does it helps ?
You have:
#property STRTodo *todoItem;
This means that STRTodo is indeed a class. Your property requires more identifiers.
#property (nonatomic, strong) STRTodo *totoItem;
In addition to this, in your -(id) init method, you should also instantiate the property.
- (id) init{
if (self = [super init]{
self.todoItem = [[STRTodo alloc]init];
}
return self;
}
Hope this helps.
EDIT: Nevermind, it seems you have found your solution.

iOS: Best way to have a global string - as for a notification name

I keep reading different things about this and it seems dangerously confusing. Can someone please tell me the proper pattern to define notification strings that can be used globally? Everything I've tried have caused linker errors. For example, in my GlobalVariables singleton I added:
#import <Foundation/Foundation.h>
extern NSString *kMPTimeChanged;
#interface GlobalVariables : NSObject etc.
And then in the init:
#implementation GlobalVariables
#pragma mark Singleton Methods
+ (id)sharedGlobals {
static GlobalVariables *sharedGlobals = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedGlobals = [[self alloc] init];
});
return sharedGlobals;
}
- (id)init {
if (self = [super init]) {
kMPTimeChanged=#"kMPTimeChanged";
return self;
}
It didn't build, I got multiple errors.
In your .h file you should write:
extern NSString * const kMPTimeChanged;
In your .m file, you should write:
NSString * const kMPTimeChanged = #"My Constant";
Both of these of these should be outside of your #interface and #implementation blocks.
I'd recommend declaring your variables as const extern. Then:
// Globals.h
extern NSString * const kMPTimeChanged;
// Globals.m
NSString * const kMPTimeChanged = #"...";
If your values are constants, just use a header, for example called Constants.h. In this header you can declare constants like this:
#define kMPTimeChanged #"kMPTimeChanged"
I don't like the extern variables. Sometimes it's hard to figure out where they came from and I wind up having to do searches on large code bases for poorly named variables which just seem to exist from no where. I guess I'm sort of in the global variables are evil crowd. Still, they are useful, so I have my own solution.
My solution is simple Constants class with a bunch of static methods, properties, whatever is needed (all read only of course). The problem is you are stuck importing this class in everywhere! There is an easy solution to that though.
In the import in your project-Prefix.pch file. This will automatically get added to all your code and you'll be able use your constants and still know where they are coming from without having to think about it.
Here is an example of my project-Prefix.pch file
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Constants.h"
#endif
Now you access Constants.serverUrl anywhere and still know exactly where serverUrl came from.

Using Protocol with Objection to get instance of object

I am new to objective C and trying to implement objection (dependency injector).
But its not working below is the code i am using
My Protocol File
#import <Foundation/Foundation.h>
#protocol InfoquestProtocolTest <NSObject>
-(void):nothing;
#end
My .h file is below
#import <Foundation/Foundation.h>
# import "InfoquestProtocolTest.h"
#interface InfoquestImplementation : NSObject<InfoquestProtocolTest>
#end
my .m file implementing protocol
#import "InfoquestImplementation.h"
#implementation InfoquestImplementation
-(void):nothing{}
#end
Code for module file of objection
#import "InfoquestTestConf.h"
#import <Objection/Objection.h>
#import "InfoquestViewController.h"
#import "InfoquestImplementation.h"
#implementation InfoquestTestConf
-(void)configure
{
[self bindClass:[InfoquestImplementation class] toProtocol:#protocol(InfoquestProtocolTest)];
}
#end
Code for getting object from objection
JSObjectionInjector *injector = [JSObjection createInjector];
[JSObjection setDefaultInjector:injector];
InfoquestTestConf *Module = [[InfoquestTestConf alloc] init];
[injector withModule: Module];
id<InfoquestProtocolTest> testing2 = [injector getObject:[#protocol(InfoquestProtocolTest)];
But when i try to call using [testing2 nothing]; i am getting error and autocomplete doesnt show up nothing.
Thanks
gaurav
You have a syntax error:
You should replace:
-(void):nothing;
with
-(void)nothing;
here is an error in your syntax.please change :
-(void):nothing;
to:
-(void)nothing;
Hence you are using custom delegates. So first you have to set the delegate to your class where you are implementing the method of your protocol.

Resources