SBApplicationController issues (always nil | can't obtain logs) - jailbreak

I'm having a weird issue with a simple app I'm building using Theos.
I'm using latest Springboard headers (dumped/fixed them myself), latest ldid and libsubstrate, and I'm testing on my iPhone 5 (with iOS 7.0.4).
This is the (cutted) Makefile:
include theos/makefiles/common.mk
APPLICATION_NAME = Reboot
Reboot_FILES = main.m RebootApplication.xm
Reboot_FRAMEWORKS = UIKit
include $(THEOS_MAKE_PATH)/application.mk
And this is the code inside RebootApplication.xm:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
UIViewController *vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor redColor];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
id sbappc = [%c(SBApplicationController) sharedInstance];
NSLog(#"SBApplicationController: %#",sbappc);
NSLog(#"SBApplicationController: %#",sbappc);
NSLog(#"SBApplicationController: %#",sbappc);
NSLog(#"SBApplicationController: %#",sbappc);
NSLog(#"SBApplicationController: %#",sbappc);
return YES;
}
My questions are:
1) Why sbappc is always nil?
2) Why I don't see NSLog output in /var/log/syslog? (I see everything but this app logs!).
Thanks

SBApplicationController is a SpringBoard class. As you're running your code inside an app (not SpringBoard) the class doesn't exist.
You probably want to make a tweak.
Create a new Theos project and select the "tweak" template this time.

Related

Repeating Audio in WatchKit (AVAudioPlayer?)?

I am wanting to loop a local audio file in my Apple Watch App. Currently I am using AVAudioPlayerNode and AVAudioEngine which works well but I cannot figure out how to loop the sound.
I noticed that I can use AVAudioPlayer, which has the handy "numberOfLoops" but, for some reason AVAudioPlayer is not working on the watch. I have no idea why.
Here is my current code to play a sound:
_audioPlayer = [[AVAudioPlayerNode alloc] init];
_audioEngine = [[AVAudioEngine alloc] init];
[_audioEngine attachNode:_audioPlayer];
AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];
[_audioEngine connect:_audioPlayer to:_audioEngine.mainMixerNode format:stereoFormat];
if (!_audioEngine.isRunning) {
NSError* error;
[_audioEngine startAndReturnError:&error];
}
NSError *error;
NSBundle* appBundle = [NSBundle mainBundle];
NSURL *url = [NSURL fileURLWithPath:[appBundle pathForResource:#"FILE_NAME" ofType:#"mp3"]];
AVAudioFile *asset = [[AVAudioFile alloc] initForReading:url error:&error];
[_audioPlayer scheduleFile:asset atTime:nil completionHandler:nil];
[_audioPlayer play];
Here is the code i've tried to use for AVAudioPlayer, but does not work:
NSError *audioError;
AVAudioPlayer* player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"FILE_NAME" ofType:#"mp3"]] error:&audioError];
player.numberOfLoops = MAXFLOAT;
player.delegate = self;
[player play];
I am using WatchKit 5.0(+).
You can loop your AVAudioFile by recursively scheduling it:
__block __weak void (^weakSheduleFile)(void);
void (^scheduleFile)(void);
weakSheduleFile = scheduleFile = ^{ [self->_audioPlayer scheduleFile:asset atTime:nil completionHandler:weakSheduleFile]; };
scheduleFile();
I'm not sure if this will be a seamless loop. If it's not, you can try always having two files scheduled:
scheduleFile();
scheduleFile();
If your audio file fits into memory, you could schedule playback as an AVAudioBuffer with the AVAudioPlayerNodeBufferLoops option (N.B. only tested on simulator!):
AVAudioFormat *outputFormat = [_audioPlayer outputFormatForBus:0];
__block AVAudioPCMBuffer *srcBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:asset.processingFormat frameCapacity:(AVAudioFrameCount)asset.length];
if (![asset readIntoBuffer:srcBuffer error:&error]) {
NSLog(#"Read error: %#", error);
abort();
}
AVAudioPCMBuffer *dstBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:outputFormat frameCapacity:(AVAudioFrameCount)asset.length];
AVAudioConverter *converter = [[AVAudioConverter alloc] initFromFormat:srcBuffer.format toFormat:dstBuffer.format];
AVAudioConverterOutputStatus status = [converter convertToBuffer:dstBuffer error:&error withInputFromBlock:^AVAudioBuffer * _Nullable(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus * _Nonnull outStatus) {
if (srcBuffer) {
AVAudioBuffer *result = srcBuffer;
srcBuffer = NULL;
*outStatus = AVAudioConverterInputStatus_HaveData;
return result;
} else {
*outStatus = AVAudioConverterInputStatus_EndOfStream;
return NULL;
}
}];
assert(status != AVAudioConverterOutputStatus_Error);
[_audioPlayer scheduleBuffer:dstBuffer atTime:nil options:AVAudioPlayerNodeBufferLoops completionHandler:nil];
[_audioPlayer play];

How to add a method with multiple parameters to the selector of a button

I get this error Terminating app due to uncaught exception 'NSInvalidArgumentException when I try to add a method with multiple parameters to the selector of a button
[viewButton addTarget:self action:#selector(loadDocument: inView:) withObject:cerereIndemnizatie.fisier withObject:self.myWebview forControlEvents:UIControlEventTouchUpInside];
This is the method
-(void)loadDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *path = [[NSBundle mainBundle] pathForResource:documentName ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
I don't know why you think you can do this or why would UIButton respond to the addTarget:selector:withObject:withObject:forControlEvents: selector... (Seriously, don't guess, read the documentation...)
You can achieve similar behavior by using associated objects:
UIButton *btn = // create the button
objc_setAssociatedObject(btn, "firstObject", someObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(btn, "secondObject", otherObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[btn addTarget:self action:#selector(click:) forControlEvents:UIControlEventTouchUpInside];
- (void)click:(UIButton *)sender
{
id first = objc_getAssociatedObject(btn, "firstObject");
id second = objc_setAssociatedObject(btn, "secondObject");
// etc.
}

NSException error seems to occur randomly

This code was working fine, now for some reason I'm getting an NSException error that's generating a SIGABRT at the following line of code...
self.popoverController = [[[UIPopoverController alloc] initWithContentViewController:wbPopOverController] autorelease];
Here's the method it's located in...
-(IBAction)showPop:(id)sender {
//close any open popovers
[self.popoverController dismissPopoverAnimated:NO];
// Initialize wbPopUpViewController
PopoverAircraftClass *wbPopOverController = [[PopoverAircraftClass alloc] initWithNibName:#"PopoverAircraftClass" bundle:[NSBundle mainBundle]];
wbPopOverController.contentSizeForViewInPopover = CGSizeMake(175, 216);
wbPopOverController.delegate = self; //for update
[wbPopOverController setAircraftList:aircraftList withCurrentValue:activeRegistration];
// Object converted to UIPopOverController (retained so we can reference it)
self.popoverController = [[[UIPopoverController alloc] initWithContentViewController:wbPopOverController] autorelease];
self.popoverController.passthroughViews = [NSArray arrayWithObject: self.view];
[self.popoverController presentPopoverFromRect:[sender frame] inView:self.layoutViewIB permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
[wbPopOverController release];
}
I'm new at this as you can probably tell. Any ideas as to what's generating the NSException?

Loading database at start up slows down the app

i m not sure how to describe this as i m new with all the developing and i m really looking forward to an answer from you guys. I know you can be very busy but please try to HELP me!
Here it goes. I have an app that loads a very large database (although it only has 100 entries it contains HiRes images (100MB) ).
At start up a tableview presents the rows -records (using only 3 attributes from the database). However it seems that the WHOLE database (including the images) is loaded at start up!
IS THERE A WAY TO ONLY LOAD THE 3 attributes (something like "select") when the app starts and then when the user moves to didselectrowatindexpath load the rest of the record?
Because i have NO IDEA where to look or what to do i would appreciate some coding help!
here is the code i m using:
#pragma mark -
#pragma mark App support
- (NSFetchedResultsController *)resetFetchedResultsController:(NSPredicate *)predicate cached:(BOOL)cached
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Records" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *partDescriptor = [[NSSortDescriptor alloc] initWithKey:#"displayOrder" ascending:YES];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects: partDescriptor, nameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
if (predicate != nil)
[fetchRequest setPredicate:predicate];
NSString *cacheName = nil;
if (cached)
cacheName = #"Root";
NSFetchedResultsController *aFetchedResultsController = [[[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:cacheName] autorelease];
aFetchedResultsController.delegate = self;
[fetchRequest release];
[partDescriptor release];
[nameDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![aFetchedResultsController performFetch:&error]) {
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
return aFetchedResultsController;
}
- (void)showRecords:(Records *)records animated:(BOOL)animated {
.
RecordsDetailViewController *detailViewController = [[RecordsDetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
detailViewController.records = records;
[self.navigationController pushViewController:detailViewController animated:animated];
[detailViewController release];
}
#pragma mark -
#pragma mark Table view methods
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.backgroundColor = [UIColor lightGrayColor];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger count = [[fetchedResultsController sections] count];
if (count == 0) {
count = 1;
}
return count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger numberOfRows = 0;
if ([[fetchedResultsController sections] count] > 0) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
numberOfRows = [sectionInfo numberOfObjects];
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *RecordCellIdentifier = #"RecordCellIdentifier";
RecordTableViewCell *recordCell = (RecordTableViewCell *)[tableView dequeueReusableCellWithIdentifier:RecordCellIdentifier];
if (recordCell == nil) {
recordCell = [[[RecordTableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:RecordCellIdentifier] autorelease];
recordCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[self configureCell:recordCell atIndexPath:indexPath];
return recordCell;
}
- (void)configureCell:(RecordTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// Configure the cell
Records *records = (Records *)[fetchedResultsController objectAtIndexPath:indexPath];
cell.records = records;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.searchDisplayController.isActive)
[self.tableView reloadData];
Records *records = (Records *)[fetchedResultsController objectAtIndexPath:indexPath];
[self showRecords:records animated:YES];
}
//this is from the RecordTableViewCell.m to show you the attributes i m using:
#pragma mark -
#pragma mark Record set accessor
- (void)setRecord:(Record *)newRecord {
if (newRecord != record) {
[record release];
record = [newRecord retain];
}
imageView.image = [UIImage imageNamed:#"icon.png"];
nameLabel.text = record.name;
overviewLabel.text = record.overview;
partLabel.text = record.part;
}
thanks again...
I would separate the large file from the metadata, because I like to have the freedom to manage these expensive resources seParately. Then I could store them differently, eg filesystem, or http server. This allows me to cache them or send them to remote locAtions proactively to reduce the download times
The rest of the table can then fit in less blocks in the database so less disk access is needed. Many databases do this internally anyway, eg postgresql
You can the just refer to the heavy resource by Id
Ok here it goes. I ve gave up the idea of loading separately the attributes that i need at start up.
What i ve done AND NOW WORKS FLAWLESSLY is to do create RELATIONSHIPS in my model. Images are now loading only when called!
This solution was in my mind but because i had already populated my database it was difficult for me to repeat this step.
However i m glad that i did!
NOW it works as it should!!
Happy Developer!!

Help with UITableView / Navigation Setup with UITabBar Interface

I'm trying to set up a Tab Bar Application as my root controller, and one of the tabs to be a Navigation setup. On my Root View Controller of the Navigation View, I have one child level that is a subclass of the UIViewController called IntervalViewController.
I have this in my Root View Controller (IntervalSetupViewController.m):
#import "IntervalSetupViewController.h"
#import "IntervalViewController.h"
#implementation IntervalSetupViewController
#synthesize controllers; // My Array for the Table View Cells
- (void)viewDidLoad {
self.title = #"Interval Setup";
NSMutableArray *array = [[NSMutableArray alloc] init];
// Interval List Setup
IntervalViewController *newInterval = [[IntervalViewController alloc]
initWithStyle:UITableViewStylePlain];
newInterval.title = #"Interval 1";
[array addObject:newInterval];
[newInterval release];
self.controllers = array;
[array release];
[super viewDidLoad];
}
- (void)viewDidUnload {
self.controllers = nil;
[super viewDidUnload];
}
- (void)dealloc {
[controllers release];
[super dealloc];
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
return [self.controllers count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *IntervalCell = #"IntervalCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:IntervalCell];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:IntervalCell] autorelease];
}
// Configure the cell
NSUInteger row = [indexPath row];
IntervalViewController *newController = [controllers objectAtIndex:row];
cell.textLabel.text = newController.title;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark Table View Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
IntervalViewController *nextController = [self.controllers objectAtIndex:row];
[self.navigationController pushViewController:nextController animated:YES];
}
#end
This is the error screen from the console:
* -[IntervalViewController initWithStyle:]: unrecognized selector sent to instance 0x3b33e60
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[IntervalViewController initWithStyle:]: unrecognized selector sent to instance 0x3b33e60'
I assume that I am passing an invalid argument to my initWithStyle method, but I thought UITableViewStylePlain was a valid parameter. Am I setting this up right? I was following the example in APress Beginning iPhone Development 3 book and trying to modify it a little to what I wanted to do, but I'm new to coding. Thanks!
initWithStyle is used to initialize a UITableViewController not a UIViewController

Resources