TWRequest and ARC - using a value elsewhere in a project - automatic-ref-counting

I am using ARC with TWRequest. I have successfully returned a search from twitter and created an array of the results. Here is my code...
NSArray *results = [dict objectForKey:#"results"];
//Loop through the results
NSMutableArray *twitterText = [[NSMutableArray alloc] init];
for (NSDictionary *tweet in results)
{
// Get the tweet
NSString *twittext = [tweet objectForKey:#"text"];
// Save the tweet to the twitterText array
[twitterText addObject:twittext];
}
NSLog(#"MY ************************TWITTERTEXT************** %#", twitterText ); </p>
My question is, I want to use twitterText later in the .m file under cellForRowAtIndexPath but as soon as the loop through (as above) is finished it is being released under ARC. I have set the property as strong in my .h file (as well as declaring it above just prior to the loop). Printing a log straight after the loop through as above prints the twitterText Array fine but the same Log in cellForRowAtIndex path method returns a blank. Any help would be appreciated. Thanks. Alan

Alan,
You do not appear to be saving twitterText in any permanent ivar. As the code is written above, ARC properly deallocates twitterText after the log statement.
Hence, just assign twitterText to an ivar in your controller.
Andrew

Related

Constantly generating QPixmap* fails after a number of iterations

I am using the following code in order to generate QPixmap* pointers and then insert them into QHash<QString, QPixmap*> (I will show only the pointers generation code since this is the one that fails).
QPixmap* MyClass::loadImg(QString fileName)
{
QImage qimage(fileName);
if (qimage.isNull()) {
qDebug() << "Cannot load image " << fileName;
}
QPixmap *image = new QPixmap(fileName);
return image;
}
The problem that I have is the following:
For the first about 200 calls the method works fine - it is being called on a loop that iterates through the image files of a directory. Then suddenly the QPixmap* starts returning QPixmap(null) for no apparent reason.QImage is also null when that happens.
I have checked and made sure that the path is fine. Also, I have tried with various sets of images and the same always happens - it runs with no problems the ~200 calls and then starts generating nulls.
Any help would be appreciated.
Thank you.
Just don't create it on heap. QPixmap is implicitly shared.

Is there a way to access ALAssets information outside of resultBlock?

Okay so I have my ImagePicker all setup and the ALAssetLibrary setup to get the Picture and Title (if it exists for existing pictures or generic text for a new picture) but now I'm trying to figure out if there's a way I can access this information outside of the block call from the assetForURL method. So here's my code just so I can show what's happening (this is in the viewDidLoad method of a screen that is displayed after a picture selection is made)
__block NSString *documentName;
__block UIImage *docImage;
NSURL *resourceURL = [imageInfo objectForKey:UIImagePickerControllerReferenceURL];
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *asset)
{
ALAssetRepresentation *imageRep = [asset defaultRepresentation];
//Get Image
CGImageRef iref = [imageRep fullResolutionImage];
//If image is null then it's a new picture from Camera
if (iref == NULL) {
docImage = [imageInfo objectForKey:UIImagePickerControllerOriginalImage];
documentName = #"New Picture";
}
else {
docImage = [UIImage imageWithCGImage:iref];
documentName = [imageRep filename];
}
};
// get the asset library and fetch the asset based on the ref url (pass in block above)
ALAssetsLibrary *imageAsset = [[ALAssetsLibrary alloc] init];
[imageAsset assetForURL:resourceURL resultBlock:resultblock failureBlock:nil];
Now I want to be able to use the two variables (documentName and docImage) elsewhere in this ViewController (for example if someone wants to change the name of the document before they save it I want to be able to revert back to the default name) but I can't seem to figure out what I need to do so these variables can be used later. Don't know if this makes much sense or not, so if I need to clarify anything else let me know.
Okay so I figured out that the problem wasn't with the code but with my logic on how I was using it. I was trying to do this on the Modal View that was presented after an image was selected instead of just doing this in the ImagePicker screen and then calling the Modal window inside of the result block code.

useLayoutToLayoutNavigationTransitions in iOS7 crash

I am building an iOS7 app and I am trying to make use of the new useLayoutToLayoutNavigationTransitions effect. I have 2 UICollectionViewControllers and when I do the following I get the transition effect
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondVC.useLayoutToLayoutNavigationTransitions = YES;
[self.navigationController pushViewController:secondVC animated:YES];
this works fine but what I want to do is make an api call and then in the completion block I want to push onto the nav stack like so
[webAPI getDetailsWithParams:params andCompletionBlock:^(id dict) {
//some work on the result
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondVC.useLayoutToLayoutNavigationTransitions = YES;
[self.navigationController pushViewController:secondVC animated:YES];
} andErrorBlock:^(NSError *error) {
}];
but this crashes every time with the following msg
-[UICollectionView _invalidateLayoutWithContext:]: message sent to deallocated instance 0x17a26400
can anyone tell me what I am doing wrong in this case? How can I get the transition effect when pushing from completion block?
EDIT: by changing it to the following I was able to transition to the second viewcontroller.
MyLayout *layout = [[MyLayout alloc] init];
SecondViewController *expandedVC = [[SecondViewController alloc] initWithCollectionViewLayout:layout];
and I also deleted the nib file that went with the file. nib file just consisted of a collection view and it was the file owners view.
While I can now transition I still do not understand why I could not do the previous nib method with in a block. So I would be grateful if someone could shed some light on it for me.
In order to use UICollectionViewController's useLayoutToLayoutNavigationTransitions to make transitions, the layout of the SecondViewController must be known. However, if you use initWithNibName:bundle: initializer, layout is not internally prepared yet, making your desired transitions impossible. As you mentioned in your edited question, you have to use [UICollectionViewController initWithCollectionViewLayout:] to initialize your second UICollectionViewController. Since your xib file has the same name as your class name, SecondViewController.xib is going to be loaded automatically by UIViewController, superclass of UICollectionViewController.
I think you were making UIKit calls from a thread that wasn't the main thread

Add NSString to NSMutableArray if NSString is not already pressent - not working

Can't understand why this won't work, it simply says id num hasn't been used before every time... and never adds it to the array. Any help on this would be much appreciated. I'm almost certainly missing something obvious, but its driving me mad.
- (IBAction)idNumInputEnd:(id)sender
{
// Check if ID Number has been used before, if it hasnt, add it to the list.
NSString *idNumCheck = idNumberInput.text;
if ([idNumberList containsObject:idNumCheck])
{
NSLog(#"This id number has been used before, ask user if he would like to reload the data");
}
else
{
NSLog(#"This id number hasn't been used before and is thus being added to the array");
[idNumberList addObject:idNumCheck];
}
}
My suspect (shared by Martin, as per his comment) that idNumberList has never been allocated and initialized to an empty NSMutableArray.
If that's the case ARC will assign nil to idNumberList, therefore [idNumberList containsObject:idNumCheck] will evaluate to nil, as well as [idNumberList addObject:idNumCheck]
In other terms your evaluated code becomes something like
if (nil) {
NSLog(#"This id number has been used before, ask user if he would like to reload the data");
} else {
NSLog(#"This id number hasn't been used before and is thus being added to the array");
nil;
}
Given that, the else branch will always be taken, the addObject call to a nil object will fail silently and this causes the behavior you're experiencing.
To fix that, initialize idNumberList like follows:
idNumberList = [[NSMutableArray alloc] init];

Please explain me how to control a Table View in Cocoa?

I search Google to find a good answer but the most tutorials are shown in previous Xcode Versions...
Also, I don't want to drag-n-drop cells from the Interface Builder, but to control the Table View programmatically (from an NSObject subclass file).
What I currently do is this: 1. Create a file named tableController.h that is a subclass of NSObject.
2. I create an NSObject Object in my Nib File (and set it as a subclass of tableController).
3. I drag a Table View to my window.
4. I CTRL+Drag from the Table View to my tableController.h so to create the outlet "tableView"
5. I create these functions in the interface file:
-(int)numberOfRowsInTableView:(NSTableView *)cocoaTV;
-(id)tableView:(NSTableView *)cocoaTV:objectValueForTableCollumn:(NSTableColumn *)tableCollumn row:(int)row;
6. I implement the functions like this:
-(int)numberOfRowsInTableView:(NSTableView *)cocoaTV{
return 5;
}
-(id)tableView:(NSTableView *)cocoaTV:objectValueForTableCollumn:(NSTableColumn *)tableCollumn row:(int)row{
NSArray *tvArray = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
NSString *v = [tvArray objectAtIndex:row];
return v;
}
Then I CTRL+Drag from the Object in the Interface Builder to the Table View to set the dataSource and to set it as delegate.
When I build and Run the App it shows that it has created the 5 Rows but in every cell in every column it says "Table View Cell".
Any help would be appreciated....
-(id)tableView:(NSTableView *)cocoaTV:objectValueForTableCollumn:(NSTableColumn *)tableCollumn row:(int)row is wrong.. i'm not sure how it compiles, to be honest (unless there was an error copy/pasting it). the method should look like:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSArray *tvArray = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
NSString *v = [tvArray objectAtIndex:row];
return v;
}

Resources