id object in theos mobilesubstrate tweak , i can't disable this -(id) - objective-c

-(id)initWithUserSettings:(id)userSettings mqttSender:(id)sender;
NSDictionary *settings3=[[NSDictionary alloc] initWithContentsOfFile:#"/var/mobile/Library/Preferences/myfilehere.plist"];
if ([[settings3 objectForKey:#"invisiblechat"] boolValue]){
return NULL;
}
else{%orig;}
[settings3 release];
}
I don't know if this code is the right one, I am searching 2 days without an answer. On -(void) this code works really good and it keeps the -(void) disabled until the objecForKey is disabled. What I want is to keep the (id)mqttSender disabled/enabled with the toggle, I can't do it though. Any help please?

Im not quite sure what you are trying to achieve from your explanation but if your going to init a class that is a subclass of NSObject you need to be at least call [super init] and return self, if you dont whatever is calling the init method will fail to get a reference to that object.
Setting a return value of 'void' means that the method shouldn't return anything, if you set 'id', then 'id' is a representative of a value that you haven't defined so it can be nearly anything.
With your method you are setting a return value of 'id' which means you should be returning something from that method. At the moment you have a single return inside of your 'if' statement, but after that your method is open ended and doesn't return anything. Xcode will throw up a compile error in this case because you are failing to return anything and it's expecting at least something to come out of the method, even if it's nil.
One other thing: you only end a method deceleration with a semi-colon when defining a method/function, when you implement the method/function you don't need a semi-colon as you are following it with curly braces which contain your code for that method/function.

Related

Initializing a constant that's value takes a completionBlock argument in its initializer

I have a property, that in Objective-C I created like this:
self.myProperty = [[MyClass alloc] initWithCompletionBlock:^(MyClass *object) {
dispatch_async(dispatch_get_main_queue(), ^{
[self doSomethingAfterInitialization];
});
}];
And it worked great. Initialization of the MyClass object could create an indeterminate amount of time, so I passed a completionHandler in to it. When it finished, doSomethingAfterInitalization: would handle business.
Now in Swift, I'm trying to create the same object and assign it to a property, with problems.
The property never will change, so it makes sense to me to create it as a Swift constant.
So I'm trying it like this:
let myProperty = MyClass(completionBlock:{ (MyClass) -> (Void) in dispatch_async(dispatch_get_main_queue(), doSomethingAfterInitialization())})
To me that seemed like a direct translation... but the Swift compiler tells me that's not correct, via the error
Use of instance member 'doSomethingAfterInitialization' on type 'MyViewController'; did you mean to use a value of type 'MyViewController' instead?
Well that didn't help much. So instead I tried changing the call to the doSomethingAfterInitialization function to self. doSomethingAfterInitialization(), in which case I see
Value of type '(NSObject) -> () -> TodayWidgetTableViewController' has no member 'doSomethingAfterInitialization'
Any idea how I can fix this? Obviously my initializer is a little weird in the first place, so I'm wondering if this is something that doesn't really translate at all to Swift.

Obj C - Is there a way to make a method return the method in which it is called?

I want to know whether there is the way to achieve the following requirement:
First, there is a methodA, which takes an input objA and check whether objA is valid for the method. If it's valid, then it returns an object objB. However, if objA is not valid, it just returns objA itself. Note that even if objA is valid, the returned objB may still be the same with objB.
Then, there is a methodB and in the method, methodA is called. If the input of methodA is valid, the program go on without error. However, if methodA is called with invalid input, then methodB should terminate (a.k.a return with a certain string signaling an error) to prevent future crash.
The current solution that I could think of is to create a (BOOL)methodAInputIsValid:(obj)input and in methodB there is:
if(methodAInputIsValid:input) {
obj objReturn = methodA:input;
}else{
//show error warning
return;
}
//continue doing something with objReturn and finally return some valid thing
A problem of the code is that (BOOL)methodAInputIsValid:(obj)input and methodA:(obj)input share a lot of code in common because there is a validity-test in methodA. So I want to use the validity-test more efficiently so that it will work for methodB and drop the (BOOL)methodAInputIsValid.
Here is one possible application that I could think of:
In a program the user is asked to enter a string that will direct the action of the program. However, the input string may need to be standardized such as converting all letters to lower-case and converting all single quotation to double quotation and auto-complete any missing right parenthesis or quotation marks. However, if the user is just entering nonsense that cannot be standardized, then the program should terminate and warn the user of the problem. The two methods are (BOOL)isStandardizeable:(NSString *)input and (NSString *)standardize:(NSString *)input. Because (NSString *)standardize already returns an NSString *, I can't make it to return another BOOL, right? So the following code is not achievable:
if(standardize:input){
NSString *result = standardize:input;
} else {
NSLog(#"unrecognizable input!");
return;
}
//continue...
Can anyone think of a way to do this?
Realistically, I'd just have methodA return nil if the input is not valid. This is a fairly common method to signal failure to a caller. If you really need the "identity" part of the method, just have callers do
id res = [... methodA:input];
if(res == nil)
res = input;

Method works correctly when called from within its class but not otherwise

I wrote this function in my RootViewController. appRecord is an object holding an XML attribute.
- (NSString*) getString:(int)row{
AppRecord *appRecord = [self.entries objectAtIndex:row];
NSString *appName = appRecord.appName;
return appName;
}
I want to use this function again by writing this:
RootViewController *record = [RootViewController new];
NSString *appsName = [record getString:0];
NSLOG(appsName);
After I compiled, it didn't return anything, but it works and returns appsName if I use this function inside the RootViewController class ([self getString:0]), so I know there is no problem with the function. When I tried to change return appName to return #"test", it worked and returned something when I accessed it from the other class.
This means there is a problem with this appRecord; it was returned inside the class but returns nothing when I access it from another class.
How to solve this problem?
You are getting your AppRecord from self.entries in the instance of RootViewController record. This means unless your new initializer initializes and populates its entries variable (array by the looks of things) before you call getString:, it won't be able to return anything since that array is empty.
Beyond that, I don't know if you want your getString:(int) method to access a different array, or if the problem is in your initialization of RootViewController (more likely)
Maybe I don't understand your question, but if you are relying on the NSLog statement to see if the function is returning anything, you should change it to:
NSLog(#"%#", appsname);

Selectors in Cocos2d schedule method

So I am doing this to initialize my selector:
//In .h
SEL selectors[3];
//In .m
selectors[0] = #selector(rotate);
selectors[1] = #selector(discharge);
And here is the problem:
When I call this in my init method in Cocos2d like this:
[self performSelector:selectors[0]];
it works fine, but when I call this line of code in a method called moveThings which is invoked through the schedule ([self schedule:#selector(moveThings:)]) at the end of my init method in Cocos2d it gives EXC_BAD_ACCESS. What is the problem with scheduling things?
UPDATE:
I have found there is a problem with the rotate function (the function being stored in selector[0]). Here it is:
-(void)rotate:(ccTime)delta {
if (((CCSprite *)[creature objectAtIndex:0]).rotation < 360) {
((CCSprite *)[creature objectAtIndex:0]).rotation++;
}
else {
((CCSprite *)[creature objectAtIndex:0]).rotation++;
}
}
If I comment the contents of the method out it works fine when called through moveThings and init.
If I change the methods contents with:
((CCSprite *)[creature objectAtIndex:0]).rotation++;
It fails... But, again, I would like to state that all of these things do work if I call it in my init method, even call it twice in a row, but it will not work (except when I take out the contents of the rotate method) if I call it through the moveThings: method which is being invoke through the schedule method it fails.
Further update:
If I call:
((CCSprite *)[creature objectAtIndex:0]).rotation++;
In moveThings (which is being, as I've said before, invoked by the schedule:(SEL) method) it fails. Where as long as it is not invoked through a method that is the called by schedule it works.
The problem is that when you call performSelector there are only two options:
have your selector take no arguments and leave the ":" off the #selector(foo) definition.
have your selector take either one or two arguments which both must be an NSObject or subclass
it is the latter that is messing you up here I suspect.
Here are the three forms of performSelector:
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
You'll note that the withObject arguments are all of type id which is an Objective C object.
The selector you're trying to use takes a ccTime which is a float and not an Objective C object as it's param and that is why things are crashing:
-(void)rotate:(ccTime)delta;
One option is to make a wrapper method that takes a wrapped ccTime and unwraps it and calls the rotate:(ccTime) method:
- (void) wrappedRotate: (NSNumber*) inDelta
{
[self rotate: [inDelta floatValue]];
}
then use
selectors[0] = #selector(wrappedRotate:);
and then call via:
[self schedule: #selector(moveThings:)]); // cocos2d schedule
...
- (void) moveThings: (ccTime) dt
{
[self performSelector: selectors[0] withObject: [NSNumber numberWithFloat: dt]];
...
}
One reason you are getting confused is because Cocos2d is using #selector in somewhat more complicated ways (see CCScheduler.m in the CCTimer::initWithTarget:selector:interval: and CCTimer::update: method in particular).
disclaimer: code typed into SO so not checked with a compiler, but the essence of what you need should be here.
One problem for sure is that you are using a variable declared inside a .h while initializing it inside the relative .m. According to the linking I'm not sure that just one variable selectors will exist (so that different files that include .h will have different versions).
First of all I suggest you to try adding the keyword extern to have
extern SEL selectors[3];
to tell your linker that it is initialized inside the relative .m and to use just that one.
I think your problem stems from your method definition which is - (void)rotate; and not - (void)rotate:(ccTime)dt;
You should adjust your selectors likewise.
If your method does not have any arguments then do not use a colon in your selector call.
// Requires #selector(foo:)
- (void) foo:(id)sender;
// Requires #selector(foo)
- (void) foo;

Subclassing and Casting in Objective C

I came across a strange problem today. I created a subclass of UIView and added only 1 method to the template code provided by xcode.
#interface FloatView : UIView {
}
- (void)floatTest:(CGFloat)x;
#end
- (void)floatTest:(CGFloat)x {
NSLog(#"float was %f", x);
}
Then in my appDelegate I had code like this:
UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Pretty simple, right? What should this print out? I thought it would something like "10.0000", but no, it prints out "0.000000".
I wrestled with this for hours, trying to figure out what I was doing wrong, and then I changed the code in my appDelegate to
FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Only then, did it print out the expected "10.0000". Why is this so? I've declared FloatView as a subclass of UIView, shouldn't I be able to assign a FloatView object to a UIView pointer without problems?
Even though floatView was declared a pointer to a UIView, it's really a floatView and it should be able to handle the floatTest message? Am I totally off base here?
Actually, polymorphism is working as expected. If it didn't work, nothing would have been printed (in your example, 0.0000 is being printed). The thing is, while your instance actually responds to testFloat:10.0f message, since the compiler can't statically see the method declaration (as UIView class doesn't declare such a method), it assumes that your method takes ... as argument and returns id.
When CGFloat is passed to a method that expects variable number of arguments (...), it's promoted to double. Thus, the receiving method is passed a double argument and thinks it's a float and it doesn't get printed correctly.
You can verify this behavior by changing NSLog line to:
NSLog(#"%f", *(double*)&x);
When the compiler sends the message to FloatView* rather than a UIView*, it can find the exact signature of the method. It can see it really expects CGFloat and doesn't promote the argument to double. As a result, it works correctly.
Additionally, if UIView* contained the method declaration that took a CGFloat, the compiler would call the method appropriately. To summarize, this is not a polymorphism issue; it's a missing method signature issue.