My code here(METHOD DEFINITION)
- (void)info:(NSString *)idno info1:(NSString *)package info2:(NSString *)rate info3:(NSString *)type info4:(NSString *)status;
{
//CODE HERE
}
My code here(METHOD CALLING)
[self performSelector:#selector(info:info1: info2:info3:info4:) withObject:#"a" withObject:#"b" withObject:#"c" withObject:#"d" withObject:#"e" ];
MY app displays the fallowing error:
No visible #interface for 'ViewController' declares the selector 'performSelector:withObject:withObject:withObject:withObject:withObject:'
Please help how to solve this problem
you can directly called the method as like instead of performSelector
[self info:#"a" info1:#"b" info2:#"c" info3:#"d" info4:#"e" ];
else if you want to continue your work with the help of performselector see this already answered in SO
This is how you have to do.
in viewDidLoad
// create a dict
NSDictionary *myDict = [[NSDictionary alloc] initWithObjectsAndKeys: #"my_pack" , #"package" , #"my_rate" , #"rate" , #"my_type", #"type" , #"my_status", #"status" , nil];
// Call your func
[self passMyValueHere:myDict];
your func
- (void) passMyValueHere : (NSDictionary *) myValues{
}
Related
I have production code which I see that it crashes once in a while with a EXC_BAD_ACCESS KERN_INVALID_ADDRESS on the block handler. I could for the life of me figure out what is wrong with my code. I have tried to reproduce this and could not in my controlled environment. Here is the stripped out and cleaned up code :
Code Snippet :
typedef void (^TestCallBackHandler)(NSString* location, NSError* error);
#interface _TestClass : NSObject
#property (nonatomic, copy) TestCallBackHandler handler;
#property (nonatomic, strong)NSTimer *endTimer;
- (void)fireOneOff:(TestCallBackHandler)handler;
#end
#implementation _TestClass
- (void)fireOneOff:(TestCallBackHandler)handler
{
_handler = handler;
NSLog(#"** New %p %# Incoming %p, %# Ours %p %#",self,self,handler, handler, _handler, _handler);
_endTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(_stop) userInfo:nil repeats:NO];
}
- (void)dealloc
{
NSLog(#"%# Dealloced",self);
_handler = nil;
}
- (void)_stop
{
NSLog(#"** Stopping ? %#",self);
if (_handler)
_handler([NSString stringWithFormat:#"Hello %#",[NSDate date]], nil);
}
#end
The calling code in my class is defined as :
#property (nonatomic, strong)_TestClass *testClassInstance;
and called like this :
- (void)startTestClass {
_testClassInstance = [[_TestClass alloc] init];
[_testClassInstance fireOneOff:^(NSString *newString, NSError *error) {
NSLog(#"Got new String! %#",newString);
_testClassInstance = nil;
}];
}
Few things to note :
The startTestClass can be called multiple times
The app wakes up in the background and this can be created.
Any pointers, help highly appreciated.. I just cant put a finger in this code and say that is what is wrong. Please help!
Two hints which occur a little bit strange to me:
First: why are you setting the object to nil in it's own block.
- (void)startTestClass {
_testClassInstance = [[_TestClass alloc] init];
[_testClassInstance fireOneOff:^(NSString *newString, NSError *error) {
NSLog(#"Got new String! %#",newString);
_testClassInstance = nil;
}];
}
Second your object may be released already and the NSTimer is trying to execute a method on a release object
- (void)fireOneOff:(TestCallBackHandler)handler
{
_handler = handler;
NSLog(#"** New %p %# Incoming %p, %# Ours %p %#",self,self,handler, handler, _handler, _handler);
_endTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(_stop) userInfo:nil repeats:NO];
}
I also dont get what the code does exactly and why. I believe there would be an easier and better maintainable solution for what you are achieving in this class.
If you want to have more information about EXC_BAD_ACCESS, then you can turn of NSZombies. In Xcode go to Product > Scheme > Edit Scheme and set checked Enable Zombie Objects.
looking for little help on accessing readonly property with Kiwi.
In short, I want to test if _myReadOnlyDict gets initialized or not.
Problem is that myReadOnlyDict is still always empty(has no contents), despite that in beforeEach block it is mocked and a value added to it.
// All these return 0
ad.myReadOnlyDict.count;
[[ad myReadOnlyDict] allKeys].count;
[ad myReadOnlyDict].count;
What I am missing here?
Any help is appreciated!
Please see the code below:
In AppDelegate.h I have a porperty.
#property (nonatomic, readonly) NSDictionary * myReadOnlyDict;
In AppDelegate.m I have a method, which is called from AppDelegate's didFinishLaunchingWithOptions method.
- (void)initConfig
{
_myReadOnlyDict = [NSJSONSerialization JSONObjectWithData:[self jsonData] options:nil error:nil];
}
I have a Kiwi test set up
describe(#"App Delegate", ^{
__block AppDelegate *ad;
beforeEach(^{
ad = [[AppDelegate alloc] init];
NSMutableDictionary * mockedDict = [NSJSONSerialization nullMock];
mockedDict[#"my_data"] = #"my_value";
[ad stub:#selector(myReadOnlyDict) andReturn:mockedDict];
});
afterEach(^{
ad = nil;
});
context(#"when smth happens", ^{
it(#"should do smth else", ^{
[[ad should] receive:#selector(initConfig)];
// These three lines fail
[[theValue([ad myReadOnlyDict].count) shouldNot] equal:theValue(0)];
[[theValue(ad.myReadOnlyDict.count) shouldNot] equal:theValue(0)];
[[theValue([[ad myReadOnlyDict] allKeys].count) shouldNot] equal:theValue(0)];
[ad initConfig];
});
});
});
Your problem is caused by the fact that [NSJSONSerialization nullMock]returns a null mock, which is an object that does nothing for any called method, and returns nil/0 to any method that must return something.
This should work:
NSMutableDictionary * mockedDict = [#{#"my_data": #"my_value"} mutableCopy];
[ad stub:#selector(myReadOnlyDict) andReturn:mockedDict];
I am trying to pass data from one controller to another (without doing any type of animation or segue) to populate a table with an array. Populating the table is not an issue as I have been able to do that, but getting the data to the controller with the tableview has proven to be impossible.
I've been trying to figure out how to do this for the last 4 days. I've read through tons of helpful posts including: Passing Data between View Controllers, with absolutely no luck. I'm fairly new to iOS dev so maybe I'm just completely overlooking something that should be simple.
I am using SWRevealViewController for the sidebar.
WebAppViewController.m
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *html = [webView stringByEvaluatingJavaScriptFromString:
#"document.getElementById('json-ios').innerHTML"];
NSData *jsonData = [html dataUsingEncoding:NSUTF8StringEncoding];
NSError *e;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e];
NSArray *jsonArray = [dict objectForKey:#"results"];
// This is where I would like to pass jsonArray to my sidebar to populate a table (SidebarViewController) each time the page loads
.....
try using NSNotification or Singleton
NSNotification:
#implementation TestClass
- (void) dealloc
{
// If you don't remove yourself as an observer, the Notification Center
// will continue to try and send notification objects to the deallocated
// object.
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
// Add this instance of TestClass as an observer of the TestNotification.
// We tell the notification center to inform us of "TestNotification"
// notifications using the receiveTestNotification: selector. By
// specifying object:nil, we tell the notification center that we are not
// interested in who posted the notification. If you provided an actual
// object rather than nil, the notification center will only notify you
// when the notification was posted by that particular object.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveTestNotification:)
name:#"TestNotification"
object:nil];
return self;
}
- (void) receiveTestNotification:(NSNotification *) notification
{
// [notification name] should always be #"TestNotification"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
}
#end
... somewhere else in another class ...
- (void) someMethod
{
// All instances of TestClass will be notified
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:self];
}
source
Singleton:
The standard way of creating a singleton is like...
Singleton.h
#interface MySingleton : NSObject
+ (MySingleton*)sharedInstance;
#end
Singleton.m
#import "MySingleton.h"
#implementation MySingleton
#pragma mark - singleton method
+ (MySingleton*)sharedInstance
{
static dispatch_once_t predicate = 0;
__strong static id sharedObject = nil;
//static id sharedObject = nil; //if you're not using ARC
dispatch_once(&predicate, ^{
sharedObject = [[self alloc] init];
//sharedObject = [[[self alloc] init] retain]; // if you're not using ARC
});
return sharedObject;
}
#end
source
P.S.There is no way singleton won't work.
Singleton is like a static object. You would want to save data here that will be accessible by the whole app without much changes in code.(Its like a global object) whereas NSNotification is self explanatory and googlable
Use protocol or NSNotification for simple data passing ..
I am using UNIRest to make a call and return a JSON object to my app. I have it returning the proper data as a NSDictionary and it logs our perfect. I am now trying to take that data and display it inside of my view. I cannot use my dictionary outside of the callback.
I have been digging around here on StackOverflow for similar results and posts related to variables. I feel it is a scope issue with it being limited to inside of the callback block.
My header file: (UIViewController)
#property (nonatomic, strong) NSDictionary *tideData;
My implementation:
#interface TideDetailViewController ()
#end
#implementation TideDetailViewController
#synthesize tideData;
- (void)viewDidLoad {
[super viewDidLoad];
// tideData = [[NSDictionary alloc] init];
// location is working, I removed it for testing to call a static string for now
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[self.locationManager startUpdatingLocation];
NSString *locationQueryURL = #"http://api.wunderground.com/api/XXXXXXXXXXXXX/tide/geolookup/q/43.5263,-70.4975.json";
NSLog(#"%#", locationQueryURL);
[[UNIRest get:^(UNISimpleRequest *request) {
[request setUrl: locationQueryURL];
}] asJsonAsync:^(UNIHTTPJsonResponse *response, NSError *error) {
// This is the asyncronous callback block
self.code = [response code];
NSDictionary *responseHeaders = [response headers];
UNIJsonNode *body = [response body];
self.rawResults = [response rawBody];
// I tried this as self as well
tideData = [NSJSONSerialization JSONObjectWithData:self.rawResults options: 0 error: &error];
// this logs perfectly.
NSLog(#"tideData %#", tideData);
// tried setting it to the instance
//self.tideData = tideData;
}];
// returns null
NSLog(#"tideData outside of call back %#", self.tideData);
// this is where I will be setting label text for now, will refactor once I get it working
// rest of file contents........
I have tried a good amount of items related to scoping, clearly just missing the mark. Any ideas? I have searched setting global variables, etc. Been stuck on this for a bit now.
Thanks,
Ryan
The reason you see nil is because you are logging it too soon: when you call
NSLog(#"tideData outside of call back %#", self.tideData);
the get:asJsonAsync: method has not received the results yet.
You can fix this problem by adding a setter for your property, and adding some special handling to it, like this:
-(void)setTideData:(NSDictionary*)dict {
_tideData = dict;
NSLog(#"tideData outside of call back %#", _tideData);
}
This method will be called from the asynchronous code when you do the tideData = ... assignment.
Try setting the object on main thread:
[self performSelectorOnMainThread:#selector(setTideData:) withObject:[NSJSONSerialization JSONObjectWithData:self.rawResults options: 0 error: &error] waitUntilDone:NO];
- (void)setTideData:(NSDictionary*)dict {
self.tideData = dict;
}
I'm using JSONModel to retrieve data from a simple webservice. I need to get the values of key #"message" into a mutable array.
- (void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
self.dataSource = self;
NSString *conversationid = #"xx";
NSString *callURL = [NSString stringWithFormat:#"http://mydomain.com/inbox_messages.php?conversation=%#", conversationid];
_feed = [[MessageFeed alloc] initFromURLWithString:callURL
completion:^(JSONModel *model, JSONModelError *err)
{
self.messages = [[NSMutableArray alloc]initWithObjects:[_feed.messagesinconversation valueForKey:#"message"], nil];
NSLog(#"messages %#", self.messages);
}];
NSLog(#"test %#", self.messages);
}
The problem I'm experiencing is that while: NSLog(#"messages %#", self.messages); returns all the right data, NSLog(#"test %#", self.messages); returns (null).
The variable is declared in .h of my class as: #property (strong, nonatomic) NSMutableArray *messages;
This is probably a noob question but I'm a beginner and if somebody could give me a pointer in the right direction, I would be very happy.
Your NSLog for self.messages is outside of the completion block. The completion block is called after the data is loaded. The log is called immediately after creating the MessageFeed request. So, of course, the object self.messages is null because the request has not completed.
The solution to this would be to either handle all of your parsing within the completion block, or call another class method to parse the received data.
Your completion handler is being called after your NSLog("test %#", self.messages); is.
Blocks usually happen concurrently and when a certain event has occurred like the completion handler here or sometimes an error handler. By looking at your code you're probably getting something like:
test nil
messages
So your MessageFeed object is being run but it continues through your code and runs the NSLog outside of the completion handler scope first. When your JSON object has downloaded, which happens after, and parses it then runs the completion handler.
- (void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
self.dataSource = self;
NSString *conversationid = #"xx";
NSString *callURL = [NSString stringWithFormat:#"http://mydomain.com/inbox_messages.php?conversation=%#", conversationid];
_feed = [[MessageFeed alloc] initFromURLWithString:callURL //this method takes some time to complete and is handled on a different thread.
completion:^(JSONModel *model, JSONModelError *err)
{
self.messages = [[NSMutableArray alloc]initWithObjects:[_feed.messagesinconversation valueForKey:#"message"], nil];
NSLog(#"messages %#", self.messages); // this is called last in your code and your messages has been has been set as an iVar.
}];
NSLog(#"test %#", self.messages); // this logging is called immediately after initFromURLWithString is passed thus it will return nothing
}