- (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.
Related
In my app I'm accessing and changing a mutable array from multiple threads. At the beginning it was crashing when I was trying to access an object with objectAtIndex, because index was out of bounds (object at that index has already been removed from array in another thread). I searched on the internet how to solve this problem, and I decided to try this solution .I made a class with NSMutableArray property, see the following code:
#interface SynchronizedArray()
#property (retain, atomic) NSMutableArray *array;
#end
#implementation SynchronizedArray
- (id)init
{
self = [super init];
if (self)
{
_array = [[NSMutableArray alloc] init];
}
return self;
}
-(id)objectAtIndex:(NSUInteger)index
{
#synchronized(_array)
{
return [_array objectAtIndex:index];
}
}
-(void)removeObject:(id)object
{
#synchronized(_array)
{
[_array removeObject:object];
}
}
-(void)removeObjectAtIndex:(NSUInteger)index
{
#synchronized(_array)
{
[_array removeObjectAtIndex:index];
}
}
-(void)addObject:(id)object
{
#synchronized(_array)
{
[_array addObject:object];
}
}
- (NSUInteger)count
{
#synchronized(_array)
{
return [_array count];
}
}
-(void)removeAllObjects
{
#synchronized(_array)
{
[_array removeAllObjects];
}
}
-(id)copy
{
#synchronized(_array)
{
return [_array copy];
}
}
and I use this class instead of old mutable array, but the app is still crashing at this line: return [_array objectAtIndex:index]; I tried also this approach with NSLock, but without a luck. What I'm doing wrong and how to fix this?
I believe this solution is poor. Consider this:
thread #1 calls count and is told there are 4 objects in the array.
array is unsynchronized.
thread #2 calls removeObjectAtIndex:2 on the array.
array is unsynchronized.
thread #1 calls objectAtIndex:3 and the error occurs.
Instead you need a locking mechanism at a higher level where the lock is around the array at both steps 1 and 5 and thread #2 cannot remove an object in between these steps.
You need to protect (with #synchronized) basically all usage of the array. Currently you only prevent multiple threads from concurrently getting objects out of the array. But you have no protection for your described scenario of concurrent modification and mutation.
Ask yourself why you're modifying the array on multiple threads - should you do it that way or just use a single thread? It may be easier to use a different array implementation or to use a wrapper class that always switches to the main thread to make the requested modification.
I'm not really sure exactly how to describe what I want to do - the best I can do is provide some code as an example:
- (void) doStuffInLoopForDataArray:(NSArray *)arr forObjectsOfClass:(NSString *)class
{
for ([class class] *obj in arr)
{
// Do stuff
}
}
So I might call this like
NSArray *arr = [NSArray arrayWithObjects:#"foo",#"bar", nil];
[self doStuffInLoopForDataArray:arr forObjectsOfClass:#"NSString"];
and I would expect the code to be executed as if I had wrote
- (void) doStuffInLoopForDataArrayOfStrings:(NSArray *)arr
{
for (NSString *obj in arr)
{
// Do KVC stuff
}
}
Is there a way to get this kind of behavior?
I don't see much point in passing the class to the method. Run your loop as:
for (id obj in arr) {
and check the methods you want to call exist. Passing the class is only really useful if you want to check that the objects in the array are actually of that class, but you couldn't then do much with that information.
Another approach would be to create a single superclass that all the classes I'd like to use this method for inherit from. I can then loop using that superclass.
So if I want to be able to loop for MyObject1 and MyObject2, I could create a BigSuperClass, where MyObject1 and MyObject2 are both subclasses of BigSuperClass.
- (void) doStuffInLoopForDataArray:(NSArray *)arr
{
for (BigSuperClass *obj in arr)
{
// Do stuff
}
}
This loop should work for arrays of MyObject1 objects, arrays of MyObject2 objects, or arrays of BigSuperClass objects.
The more I've been thinking about this, the more I'm leaning towards this being the best approach. Since I can setup my BigSuperClass with all the #propertys and methods I'd be interested in as part of my // Do Stuff, which means I won't have to check respondsToSelector as with the other answers. This way just doesn't feel quite as fragile.
I came up with an idea while I was typing up this question, figured I might as well finish it. I just need to change how I'm doing my loop, and I don't really need to send in the class.
- (void) doStuffInLoopForDataArray:(NSArray *)arr
{
for (int i=0; i < [arr count]; i++)
{
// Do stuff
}
}
I should note that part of my // Do stuff is checking to make sure if ([[arr objectAtIndex:i] respondsToSelector:...]) before I actually try to do anything with it - and from what I understand that should prevent any nasty crashes.
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 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.
I have an noob problem and I would like you yo point me in the right direction. Basicly I have a custom class which implements the copying protocol. However when I save the class during execution the custom class i released and I get a bad access. I can see in instruments that the retain count is -2. I save the custom class with the following method:
-(void)storeDataInFile:(NSString*)dataFileName DataArray:(NSArray*)dataToStore
{
//Get the path
NSString *path = [self pathToDocumentsForDataFile:dataFileName];
//Archive the file
[NSKeyedArchiver archiveRootObject:dataToStore toFile:path];
}
Is I use the method sor saving a array with strings it works flawless. What should I look deeper into regarding my custom class?
Regards
I soved this issue, however I only provided the solution in a comment which apprantly has been deleted. So I just wanted to post the answer which indicates it was a noob mistake.
From an eralier test implementation I had the following method in the class
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
//retain is counted up
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX;
}
These methods ruined my retain count :)