iOS 7, UIView subviews is nil - ios

Why in iOS 7 [UIView subviews] is always return a nil ?
I am using this code, but already get a nil.
Bug in iOS 7 ?
EDITED:
TWTweetComposeViewController* tweetSheet = [[TWTweetComposeViewController alloc] init];
[tweetSheet setInitialText: twitter_descrp];
[tweetSheet addURL:[NSURL URLWithString: twitter_link]];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString: twitter_img]];
UIImage* uiImage = [UIImage imageWithData:imageData];
[tweetSheet addImage:uiImage];
NSLog(#"subviews: %#", [tweetSheet.view firstSubviewOfClass:[UIButton class]] );
Here firstSubviewOfClass is got from iOS7 Subviews Hierarchy
And inside a NSLog is return this:
subviews: (
)

iOS 7 hierarchy changed a lot. As one example, Apple replaced many UIButtons by table views and table view cells.
Are you sure there is actually a button in the hierarchy? For debugging, you could try to call
NSLog(#"%#", [tweetSheet.view recursiveDescription]); // (ignore the warning)
to see how the view hierarchy looks like.
However, in iOS 7 Apple has started to intentionally block access to system views (UIAlertView for an example). Sometimes because of security, sometimes because for their own reasons. That means it is possible you won't be able to access the button at all.
You shouldn't be accessing the button.

Related

launch video every time splash screen disappears in iOS app

I am little bit confused about the behaviour.
What I want to do is,
I am having two different application.
One is made by me and other is by a guy who left the company & now I have to complete his projects.
But the task to be done in both project is same.
I have to show 5 sec video when I open the app every time.
Like Some branding video. (Done in angry birds app)
I checked all the links on SO, but didn't helped any one.
My senior who left the company, he have used Main.storyboard for navigation each screen.
and I am not that much good in using storyboard.
In my app, I created navigation programatically.
When my splash screen disappears,
I show dashboard.
But before showing dashboard, I have to show the video every time.
So what I did,
I created a view controller only for Video named VideoViewController,
and call that view controller from ViewDidLoad of dashboardView.
and when my video finished,
then by using NSNotificationCenter I removed the VideoViewController.
When I Nslog the url path, its printing correct, but My app crashes after that.
I checked it by applying ExceptionalBreakpoints, but didn't helped.
Here is my code to launch video in ViewDidLoad of VideoViewController
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"video" ofType:#"mp4"]];
NSLog(#"video path :- %#",url);
playercontroller = [[MPMoviePlayerController alloc] init];
[playercontroller setContentURL:url];
[playercontroller.view setFrame:CGRectMake (0, 0, 320, 460)];
[self.view addSubview:playercontroller.view];
[playercontroller play];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:playercontroller];
and I am pushing VideoViewController from dashboard's
-(void)viewDidAppear:(BOOL)animated
method.
As I am doing any thing wrong.
As My url is getting Nslg well, so no doubt of loading video.
Please guide me for the same.
also guide me to achieve same task using storyboard.
Thanks in advance.
you shouldn't hardcode set the frame like that though..
Assuming 'self' is a ViewController (which has been properly addChildViewController'ed all the way from the RootViewController), try the next thing:
NSString *path = [[NSBundle mainBundle] pathForResource:videoFileName ofType:#"mp4"];
NSURL *url = [NSURL fileURLWithPath:path];
MPMoviePlayerViewController *videoController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[self presentMoviePlayerViewControllerAnimated:videoController];
[videoController.moviePlayer play];

Cordova on iOS: Attempt to present on a controller while a presentation is in progress

I'm having an issue where I select an image in a Cordova app and then when the image is successfully selected my plugin is supposed to launch a photo editor.
Here is the code for the show method in my plugin:
- (void) show:(CDVInvokedUrlCommand*) command
{
NSString* arg0 = [command.arguments objectAtIndex:0];
NSURL* url = [NSURL URLWithString:arg0];
NSString* imagePath = [url path];
UIImage* image = [UIImage imageWithContentsOfFile:imagePath];
self.aviary = [[AFPhotoEditorController alloc] initWithImage:image];
[self.aviary setDelegate:self];
[self.viewController presentModalViewController:self.aviary animated:YES];
}
The photo editor doesn't display and the following warning comes up:
Attempt to present AFSDKViewController: 0x9e73470 on MainViewController: 0x9fc9780 while a presentation is in progress!
So if I add a delay to my call to the plugin like the following the photo editor launches fine but I would prefer not to have to include a delay in my code just for iOS. What is the proper way to avoid this race condition?
setTimeout(function() {
// code that calls my photo editor plugin
}, 1000);

Animation Using To Much Memory iOS7

I have a series of .png images loaded into an animation, which works fine, but when I switch to another view, the memory that the animation uses is not freed up. Which takes up more and more memory every time you return to that view until eventually the app quits due to too much memory pressure.
Is there anything I can put in view diddisappear or another method to free this memory from the animation when the view is changed?
Also this only seems to happen in with my 4S running iOs 7. On my 4S with 6.1.2 it runs smoothly.
NSArray *animationArray = [NSArray arrayWithObjects:
[UIImage imageNamed:#"0001.png"],
[UIImage imageNamed:#"0002.png"],
[UIImage imageNamed:#"0003.png"],
...
nil];
self->tapanimation1.animationImages =animationArray;
self->tapanimation1.animationDuration = .5;
self->tapanimation1.animationRepeatCount = 1;
[self->tapanimation1 startAnimating];
How you alloc image in animation --- there are two ways of intializing UIImage
First is -->
[UIImage imageNamed:#"kshitij.png"];
There is issue with this method it doesnot dealloc memory , even on release .
Second is -->
If image is in your app Bundle,then always use this
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"kshitij" ofType:#"png"];
UIImage *image = [[UIImage alloc]initWithContentsOfFile:filePath];
Now use this image and make it release too , it will surely will save your some MB.
and you can also use ARC for memory saving.
Try this code --
NSSMutableArray *imageNameArray = [[NSSMutableArray
alloc]initWithObjects:#"0001",#"0002",nil];
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for(int i=0;i<imageNameArray.count;i++)
{
NSString *filePath = [[NSBundle mainBundle]pathForResource:[imageNameArray
objectAtIndex:i] ofType:#"png"];
UIImage *image = [[UIImage alloc]initWithContentsOfFile:filePath];
[imageArray addObject:image];
}
self->tapanimation1.animationImages = imageArray;
self->tapanimation1.animationDuration = .5;
self->tapanimation1.animationRepeatCount = 1;
[self->tapanimation1 startAnimating];
Now when animation does stop just release array. If you are using ARC then make it nil.
How are you navigating to your new view controller, and how are you getting back? Are you using an unwind segue? Are you presenting the new view controller as a modal and then dismissing it?
Or are you using a segue to link to the second VC, and then another segue to link back? If you are using a second (non-unwind) segue to link back, then that's your problem. That would cause you to create a new instance of your first view controller each time.
As for releasing memory, you could certainly set your view's animationImages array to inil in viewDidDisappear, and then re-load the images in viewWillAppear, but it doesn't make sense that you memory footprint would go up with each round trip to the second view controller. That indicates a problem.

UIActivityViewController taking long time to present

I made an app for iPhone. Now, I'm recreating it for iPad.
When the user selects the action button in the toolbar, a popover should show with a UIActivityViewController, but for some reason, it's taking about 10 seconds for it to show the first time. On iPhone, it takes about a second. It's the same code except for the popover.
I tried disabling the popover, but it still takes around 10 seconds to show.
Here is the code:
-(IBAction)Actions:(UIBarButtonItem*)sender
{
if ([activityPopover isPopoverVisible] == YES)
{
[activityPopover dismissPopoverAnimated:YES];
return;
}
UIWebView *currentWebView = ((TabView *)self.tabs[self.currentTabIndex]).webViewObject;
NSString *currentURL = (NSString*)[currentWebView request].mainDocumentURL;
if (currentURL == NULL) return;
BookmarkActivity *bookmarkActivity = [[BookmarkActivity alloc] init];
UIActivityViewController *sharing = [[UIActivityViewController alloc] initWithActivityItems:[NSArray arrayWithObject:currentURL] applicationActivities:#[bookmarkActivity]];
activityPopover = [[UIPopoverController alloc] initWithContentViewController:sharing];
[activityPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
I have tested on my iPad 3 and my iPad mini, both take awhile to present this.
How can I solve the problem?
Good question, I just had the same problem. It is not really solvable. However, you may improve the user experience by creating an activity indicator and then sending the initialization of the UIActivityViewController to the background:
-(void)openIn:(id)sender
{
// start activity indicator
[self.activityIndicator startAnimating];
// create new dispatch queue in background
dispatch_queue_t queue = dispatch_queue_create("openActivityIndicatorQueue", NULL);
// send initialization of UIActivityViewController in background
dispatch_async(queue, ^{
NSArray *dataToShare = #[#"MyData"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
// when UIActivityViewController is finally initialized,
// hide indicator and present it on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicator stopAnimating];
[self presentViewController:activityViewController animated:YES completion:nil];
});
});
}
It works like a charm. When the user touches the button, the activity indicator starts animating, thus indicating that the process will take a while.
I was having the same issue on iOS 7. When I removed UIActivityTypeAirDrop from the allowed activity types, however, the controller appears almost instantly.
Although these calls are already from the main thread, since iOS 7, wrapping some of those presentation calls in a dispatch block seems to greatly reduce the delay
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:activityViewController animated:YES completion:nil];
});
Had this issue myself recently. Would sometimes take nearly 4 or 5 seconds to pop up, which is a lifetime! Only the first time though. Subsequent calls were quick.
Also had a similar issue a couple of years back with the keyboard appearing slowly and someone produced a few lines of code added to the appdelegate that preloads the keyboard to get around that.
I used a similar approach here to preload the UIActivityViewController by placing this in the AppDelegate on startup. It's absolutely a hack which shouldn't be necessary but I couldn't find any other options.
let lagfreeAVC:UIActivityViewController = UIActivityViewController(activityItems: ["start"], applicationActivities: nil)
lagfreeAVC.becomeFirstResponder()
lagfreeAVC.resignFirstResponder()

Displaying a PDF with UIWebView Not Working

So, I realize that there have been many questions regarding using a UIWebView to display a PDF in an app (on the iPad). I have reviewed everything I can find but I can't seem to find any satisfaction.
What I'm trying to do is very basic so I really don't know why it's not working. All I need to do is display a locally stored PDF in the UIWebView. Essentially, all I'm getting is a black screen. If someone could take a look at my code, I'd really appreciate it. Thanks.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Segue to the materials screen.
if ([segue.identifier isEqualToString:#"materials"]) {
PDFViewController *pdfViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
pdfViewController.selectedLesson = selected ;
//Start Load PDF in UIWebView
pdfViewController.pdfWindowTitle.title = selected.titleAndSubtitle;
pdfViewController.pdfWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 704)];
NSString *urlAddress = [[NSBundle mainBundle] pathForResource:#"moonlightSonataFirstMovement" ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[pdfViewController.pdfWebView loadRequest:requestObj];
//End Load PDF
}
}
I've checked to see if my object is bring passed into the scene properly (and it is) and if I am getting a proper request out; i'm getting:
<NSURLRequest file://localhost/Users/MYCOMPUTER/Library/Application%20Support/iPhone%20Simulator/5.0/Applications/AB161E57-D942-44C2-AA75-030087820BED/iLessons%20Piano.app/moonlightSonataFirstMovement.pdf>
Also, I've have this error message:
iLessons Piano[23080:f803] DiskImageCache: Could not resolve the absolute path of the old directory.
Additionally, the NSLog message gets printed out 8 times for some reason.
The only thing I can think of is that I need to do this loading when I call my prepareForSegue function in the previous scene. That or use a different method like Quartz. But I'd rather use a UIWebView since all I really need to do is display and allow scrolling.
DiskImageCache: Could not resolve the absolute path of the old
directory.
This one isn't the real reason the app crashes. This warning can be fixed by assigning the view in the Storyboard. It seems like it's connected already but it's grey. So assign it again and it will be fine.
The real issue for me was that the PDF images were 300 DPI and it took too long to load the application. Since the debugger keeps the app from crashing it seems to work fine but the loading will take too long without the debugger and will result in a timeout crash.
There's a few things you can do. You can downscale your PDF which might be a good thing anyway since older device are even slower and it's nice to support those as well. But what really fixes it is by delaying the PageView initialization. Here's what I did:
In the RootViewController I moved the code from the viewDidLoad to a new function setupPageViewer.
And put this in the viewDidLoad:
[self performSelector:#selector(setupPageViewer) withObject:nil afterDelay:0.0f];
The delay 0.0 means it will be taken care of in the next frame which gives you the opportunity to show a loading indicator.
Enjoy!
im not sure about whats going on .. you view and webView both holding nil value.. as i told you im not involved in the storyBoard yet .. but you as a workaround solution maybe this fix your problem
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1027, 768)];
pdfViewController.view = view;
pdfViewController.pdfWebView = [[UIWebView alloc] initWithFrame:pdfViewController.view.frame];
NSString *urlAddress = [[NSBundle mainBundle] pathForResource:#"moonlightSonataFirstMovement" ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[pdfViewController.view addSubview:pdfViewController.pdfWebView];
[pdfViewController.pdfWebView loadRequest:requestObj];
As a workaround, you can disable or remove your 'All Exceptions' breakpoint. This might make debugging a little more difficult, but it's not as bad as having to relaunch the application all the time.
This is the breakpoint causing the issue. I had set it so long ago that I'd forgotten it was there

Resources