I have done a delegate , so in the class delegated, which is a UIPopover, there is a method that received an object of my PreguntasViewController. If i print the variables , there is not anything. Why could it be? Thanks.
// -- PreguntasViewController
- (void)getRespuestasDelegate {
[delegate getRespuestas:self];
}
//Delegated class
- (void)viewDidLoad
{
[super viewDidLoad];
PreguntasViewController *preguntasViewCotroller = [[PreguntasViewController alloc] init];
preguntasViewCotroller.delegate = self;
[preguntasViewCotroller getRespuestasDelegate];
}
- (void)getRespuestas:(PreguntasViewController *)preguntasViewController{
for(NSString *respuesta in preguntasViewController.preguntasArray) {
NSLog(#"%#", respuesta);
}
NSLog(#"%d", [preguntasViewController.preguntasArray count]);
NSLog(#"%#", preguntasViewController.ayudapreguntas);
}
It looks to me from your example like you are allocating an instance of PreguntasViewController and then immediately calling its getRespuestasDelegate method. I don't see anywhere that preguntasArray gets populated. Is it populated as part of the PreguntasViewController's init method? If not, I wouldn't expect there to be anything in the array.
Related
This is an implementation section of a class named "Model". Here I recursively call call the setDictionary method upto 3 layers, which raises an exception (NSMutablearray mutated while being enumerated) this exception can be avoided if I use for loop istead of forin, I would like to understand how this error occurs...Can any one help...Please dont reply with some links that point to some definition, I already read lots of documentation and I dont understand how the exception is raised in this situation.
#implementation Model
#synthesize arraySubOptions,boolHasSub;
- (instancetype)init
{
self = [super init];
if (self) {
boolHasSub = NO;
arraySubOptions = [NSMutableArray new];
}
return self;
}
-(void)setDictionary:(NSDictionary*)dict{
boolHasSub = [[[dict objectForKey:#"key_has_sub"] nullCheck:[NSString class]] boolValue];
if (boolHasSub) {
NSArray * arrayDict = (NSArray*)[self loadDataFromDB];
if(arrayDict && (arrayDict.count>0) ){
for (NSDictionary * dict in arrayDict) {
Model * objOption = [Model new];
[objOption setDictionary:dict];
[arraySubOptions addObject:objOption]; /*This is the line that raises the exception. It raised */
}
}
}
}
#end
Your method
[self loadDataFromDB]
should be altering your arrayDict, so, when you reach
[objOption setDictionary:dict];
is entering twice in that function, modifying your arrayDict and launching this exception.
Doing it with 'for' instead of 'foreach' works because you set the limits of your loop and it doesn't reach any exception if your limit isn't out of bounds. (i > arrayDict.count)
[self loadDataFromDB] returns an array which gets deallocated when the method call ends, since the object was created inside the method. So copying the returned array did the trick.
[[self loadDataFromDB] copy]
- (NSArray ) arrayWithImages:(KIImagePager)pager {
return #[
//#"https://files.parsetfss.com/3cebf0c7-ae8f-4072-bb5a-ea8d98a64e87/tfss-2d805863-4caa-4317-aa75-b865759b4c79-Image.jpg",
//#"https://files.parsetfss.com/3cebf0c7-ae8f-4072-bb5a-ea8d98a64e87/tfss-695d639d-e275-4226-be25-808cbe8f80e2-Image.jpg",
//#"https://files.parsetfss.com/3cebf0c7-ae8f-4072-bb5a-ea8d98a64e87/tfss-5a4084bb-d5fe-4ce9-a0b6-3813f205acb0-Image.jpg"];
return imageURLs;
}
This method doesn't work though I am populating imageURLs with same URLs as in the commented lines. The commented lines work perfectly but I can't use that as I don't know the URLs before hand and hence I need to populate an array and return that.
[EDIT] I am populating my array in viewDidLoad method like so:
- (void)viewDidLoad
{
[super viewDidLoad];
_imageURLs = [[NSMutableArray alloc]init];
[_imageURLs addObject:string1];
[_imageURLs addObject:string2];
[_imageURLs addObject:string3];
}
where string1...3 are from a database on the network
I just got it working with huge support from the KIImagePager's author Marcus Kida. Thanks Marcus. So for anyone who might face a similar problem, here's the solution from Marcus.
Return an instance object array like so
- (NSARRAY *) arrayWithImages:(KIImagePager)pager {
return self.imageUrls;
}
After getting your image urls/strings, reload your KIImagePager like so:
self.imageUrls = ...
[self.myPage reloadData];
And that is it.
I intend to call default init method in init method with arguments, in iOS. like this:
-(id)init{
self = [super init];
if (self) {
Office = [[NSString alloc]init];
}
return self;
}
-(id)initWithOffice:(NSString*)office{
self = [self init];
if (self) {
self.Office = itemDescription;
}
return self;
}
My question is it a good practice, What should be done?
I appreciate your response in advance,
That will work, but I would prefer the following as it doesn't allocate an empty string, only to be replaced with the initializing string:
-(id)initWithOffice:(NSString*)office{
self = [super init]; // Not [self init]
if (self) {
Office = office; // OK if using ARC
}
return self;
}
The first init method doesn't make a great deal of sense; I think simply leaving Office as nil is better (NSString objects are immutable). As pointed out by #H2CO3, the initWithOffice method becomes the designated initializer for the class and all other init methods should use it to initialize the object. With that in mind the first init method should be:
-(id)init{
return [self initWithOffice:nil];
}
Creating a method starts with initWith is to see what values will be passed. It helps you to remind which values should be sent and allocated in the method. Consider you have 4 variables to init when the view is initialized. It's best to keep a separate initWith method where you can init your view and other variables you customize.
I think you should improve you object assignning logic,Like that...
-(id)initWithOffice:(NSString*)office{
self = [self init];
if (self) {
self.Office = [[NSString alloc] initWithString:office]; //Purpose is that //the office object can only be released by the self, non other classes (The owner //of the variable should be self).
}
return self;
}
I have an helper class which has a function that makes an api call and get some json data and formats and returns an array. My TableViewController is trying to access that returned array. Yes, as you expected my tableviewcontroller viewDidLoad method is not able to access the array object returned by my helper class.
#interface MyHelperClass : NSObject
#property (nonatomic,retain)NSArray *myArray;
#end
#implementation MyHelperClass
#synthesize myArray;
- (NSArray *) returnArray{
// make api calls and return array
return myArray;
}
#end
#implementation MyTableViewController
{
- (void)viewDidLoad
{
[super viewDidLoad];
MyHelperClass *myhelper = [[MyHelperClass alloc]initWithPath:getSpacePath];
allTopics = (NSArray *)[myhelper returnArray];
NSLog(#"Load my Array%#",allTopics);
}
}
My question is, do I need to implement a delegate to pass the data around or is there any other way to pass around the data to my view controller?
P.S : I do not want to use global variable
Did this code give you any warning ?
You are trying to return an NSArray * from void returning method.
Modify it to
- (NSArray *) returnArray{ // YOU CAN RETURN id AS WELL, AS YOU ARE TYPE CASTING THE RESULT AT CALLING TIME
// make api calls and return array
NSLog (#"myArray :: %#", [myArray description]); // Post the output back here
return myArray;
}
Let me know if the problem persists.
EDIT
Set breakpoints at
allTopics = (NSArray *)[myhelper returnArray]; // AT - (void)viewDidLoad
and
return myArray; // AT HelperClass method
If first one it getting fired first, then You have to implement as #A-Live suggested in the comment.
Sorry for posting the answer so late. I figured out what the problem is. As #A-Live mentioned, the Rest API calls using AFNetworking is using async calls and hence it's not returning the array to the main thread within it's execution time. In my case,
-(void)viewDidLoad {
NSLog(#"I get called first");
MyHelper *helper = [[MyHelper alloc]init];
// returns array. However, [helper getData] is an async call under the hood. Hence myArray is nil
myArray = [helper getData];
}
To solve this problem, I took advantage of NSNotification.
#implementation MyHelper{
-(NSArray *)getData(){
[[NSNotificationCenter defaultCenter] postNotificationName:#"some.name.notification" object:JSON];
}
}
-(void)viewDidLoad(){
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loadData:) name:#"some.name.notification" object:nil];
}
-(void)loadData:(NSNotification *)notif {
// You can access the JSON object passed by the helper in here
NSArray *myArray = [notif object];
// do whatever you want with the array.
}
I hope I am detailed enough. I hope this helps someone and saves a lot of headache.
I need to create some objects that will be waiting for some event. When the waited event is triggered, the object makes some things, and then has no longer any reason to live.
I don't want to have to maintain a list of created objects, so I'd like to do something like this :
main() {
Waiter* myWaiter1 = [[Waiter alloc] initAndWaitForEvent:xxxxxxxxxx];
Waiter* myWaiter2 = [[Waiter alloc] initAndWaitForEvent:xxxxxxxxxx];
Waiter* myWaiter3 = [[Waiter alloc] initAndWaitForEvent:xxxxxxxxxx];
Waiter* myWaiter4 = [[Waiter alloc] initAndWaitForEvent:xxxxxxxxxx];
....
/* myWaiterx are retained */
/* I don't release them */
}
Waiter
- (void) catchSomeEvent:(...*)theEvent {
// do what is expected
[self release]; // Release self
/* the release is there */
}
Will this work, and work fine ?
I find it better when there’s somebody to take care of the waiters, but your code is fine. Objects can do this, there is no technical obstacle that would prevent it. Some classes from the standard library already do something similar, for example UIAlertView.
I don’t think that the static analyzer will like your current API, though. It will probably complain about leaks; it would be better to tweak the interface a bit.
#interface Waiter : NSObject {}
- (id) init;
- (void) startWaitingForEvent: (id) event;
#end
#implementation Waiter
- (void) startWaitingForEvent: (id) event
{
[self retain];
…
}
- (void) eventReceived
{
…
[self release];
}
#end
Then the memory management in user code looks better:
- (void) dispatchWaiters {
Waiter w1 = [[Waiter alloc] init];
[w1 startWaitingForEvent:…];
[w1 release];
}
An object can not suicide. It can either be killed by you(the code you sent to kill it), or by the professional killer NSAutoreleasePool. If you own it, you have to kill it.
Warning: If it doesn't die on time, the population will increase and will mess up the memory.
;-)
On some occasions [self release]; is used, for example for initializers (to force variables that a required in some way), an example:
SomeClass.m:
- (id)initWithString:(NSString *)string
{
self = [super init];
if (self)
{
if (string == nil)
{
[self release];
return nil;
}
// if required values are provided, we can continue ...
}
return self;
}
- (id)init
{
return [self initWithString:nil];
}
A caller would call this like:
- (void)testInitializer
{
SomeClass *classInstance1 = [[SomeClass alloc] initWithString:#"bla"];
// classInstance1 != nil, any method calls will work as expected ...
SomeClass *classInstance2 = [[SomeClass alloc] initWithString:nil];
// classInstance2 == nil, will ignore any method calls (fail silently)
SomeClass *classInstance3 = [[SomeClass alloc] init];
// classInstance3 == nil, will ignore any method calls (fail silently)
}
I would guess since the above works fine, you shouldn't have any issues, though it doesn't seem a very clean solution.