iky1e
iky1e
iKy1e | iOS Developer
36 posts
The blog of a teenage programmer.
Don't wanna be here? Send us removal request.
iky1e · 12 years ago
Link
This describes quite nicely some of the issues I have with iOS 7’s design principles.
I dislike iOS 7 so strongly that I feel inclined to begin this post with a disclaimer about how much I admire Apple. Apple is my hero. They’ve always inspired me to be better at what I do, even when I was an ICU nurse. But they are not perfect. I can and should criticize their worst work when I…
130 notes · View notes
iky1e · 12 years ago
Text
When the live demo works during a talk
by @f1nux
22 notes · View notes
iky1e · 12 years ago
Text
How to put UISlider's in UIScrollView's
It's a fairly simple request you'd imagine. Simply put a slider inside some content which scrolls.
As this is on iOS that content is obviously inside a UIScrollView.
  The Problem
The main problem with the above is that they don't like each other. If you place a standard UISlider inside a normal UIScrollView the scroll view delays the touches for a fraction of a second to see if you are scrolling. Here is the big problem, you swipe sideways to scroll and you, want to, swipe sideways on the sliders thumb to quickly change it's value.
As a result you have to tap, pause and then drag the slider in order to use it. Manageable but hardly smooth or ideal to use.
Of course there is a very simple way to avoid this.
scrollView.delaysContentTouches = NO;
Simple? Well, at least for me on iOS 5, a little too simple. This caused almost all objects to prevent my scrollView from scrolling, buttons, sliders, even an image view seemed to block it. So we filter for the slider?
If we look at the UIScrollView documentation we see a few little things that allow us to control the delays and cancelling touches. Creating a custom subclass gives us a little more power, but still not enough.
What do we do with our new subclass then? Well, we need to control when to allow touches to behave normally and when we should scroll.
@interface KHCustomScrollView : UIScrollView @property (nonatomic, assign) BOOL ignoreSliders; @end @implementation KHCustomScrollView @synthesize ignoreSliders = _ignoreSliders; -(BOOL)touchesShouldCancelInContentView:(UIView *)view{ if (self.ignoreSliders) { if ([view isKindOfClass:[UISlider class]]) { return NO; } else { return YES; } } return [super touchesShouldCancelInContentView:view]; } @end // Somewhere else... scrollView.canCancelContentTouches = YES; scrollView.delaysContentTouches = NO; scrollView.ignoreSliders = YES;
What we do here is tell it we want the scrollView to let all touches to start normally, but we want it to be able to cancel them if it wants to scroll. Instead of the normal behavour of delaying them until its decided whether or not to scroll it now cancels touches when it wants to. Then we have our scrollView say it can cancel touches and start scrolling for everything, other than sliders.
Now can you guess the problem here?
If we touch anywhere on the slider it will not scroll, however the slider only responds over the thumb image that indicates the value selected. But we can fix this too, however we have to work with the sliders themselves :(, although luckily we don't need to subclass them.
// Somewhere... -(void)monitorSlider:(UISlider*)slider{ [slider addTarget:self action:@selector(willSlide:) forControlEvents:UIControlEventTouchDown]; [slider addTarget:self action:@selector(didSlide:) forControlEvents:UIControlEventTouchUpInside]; [slider addTarget:self action:@selector(didSlide:) forControlEvents:UIControlEventTouchUpOutside]; [slider addTarget:self action:@selector(didSlide:) forControlEvents:UIControlEventTouchCancel]; } -(void)willSlide:(id)sender{ scrollView.scrollEnabled = NO; } -(void)didSlide:(id)sender{ scrollView.scrollEnabled = YES; } // Someone else... [self monitorSlider:slider]; // In our scrollView subclass we made earilier if ([view isKindOfClass:[UISlider class]] && !self.scrollEnabled) { return NO; }
By the way that `scrollView.scrollEnabled` is only state storage. It could have been written scrollView.tag = 42, if (scrollView.tag == 42) ...
So now we allow touches to reach things inside the scrollView, we know when the slider was touched on its thumb image, and we can control which touches are canceled and which are allowed to prevent us from scrolling.
    And finially, here's an example project on Github to show you an example for each stage of this article. Hope someone finds this useful as I couldn't find anything on the subject.
4 notes · View notes
iky1e · 12 years ago
Text
The state of toggles on iOS
Toggling things like wifi or bluetooth on and off quickly and conveniently is a feature that has been added to lots of apps and tweaks since very early on since iOS was first jailbroken.
In the past
This trend started off with things like Bossprefs which managed various settings on the device but was a stand alone app and didn't have much flexibility:
Then you have SBSettings. SBSettings got lots of attention and quickly became one of the default things people installed on their jailbroken devices once they finished jailbreaking. And of cause it has it's own API so other developers could have it control their things, such as SSH or UserAgentFaker.
The problem with SBSettings API is it was designed quite early in iOS's history and so isn't designed very natively and could be much better (more on that later). It has it's advantages though, isn't quite simple. Each toggle has a dylib with a few simple C functions. SBSettings opens them and calls the functions to make things happen or check it's state. It also includes some more advanced options like presenting extra windows to show things like a list of processes running or a slider for the brightness. As a sign of it's age it must respring to reload it's settings. When it was designed that was the norm and having a tweak which could adapt to settings on the fly without resrpinging would be a killer feature.
Now
iOS and ObjectiveC has moved on quite a bit now and is much more advanced and more refined then it was. SBSettings was good but after iOS 4 I stopped using it. This was mostly down to notification centre taking over as the "above" window on my device. Having 2 windows that drop down form the top of the screen as a control centre for my device each activated under different circumstances just feels wrong, so I don't us it anymore (and it although quite a few people still use it, it isn't as popular as it once was).
NCSettings has mostly replaced it for me. SBSettings has a mode to run inside notification centre but it just doesn't fit well. It has been adapted quite well, but it and it's toggles weren't designed for that purpose. NCSettings by comparison was designed from the start to run in the notification centre and fits in very well with a minimal stripped back design.
And now everything offers some basic controls and toggles. Deck is an example of something like NCSettings designed to do just that. However, lots of tweaks now offer some sort of toggles, Auxo for example extends the simple mute/orientation lock toggle in the switcher to a more general control of the devices basic features. The problem with all these things is they are limited to what you can convince the developer to add support for and anything like SSH or your own add-on which is a separate package and my not be installed on everyones devices is going to be a hard sale to get added. In short none of them have an API and there's defiantly not a unified API among them. The closest I've seen is a tweak using SBSettings API for itself.
Now that I've briefly outlined how toggles on iOS currently are I'm going to outline how I think they should, or rather could, be in another blog post.
0 notes
iky1e · 13 years ago
Link
So true!
I wish I could take credit for this but I can’t. Got this from an arstechnica.com forum posting from way back in June of 2010.
The forum poster’s moniker is The Real Blastdoor. Please join me in thanking him for this, because it is absolutely pure gold. Additionally, each and every word is true.
The Apple haters’ stages of grief go something like this:
Predict failure of new Apple product
Attribute early success of new Apple product to rabid fanbois affected by the reality distortion field
Attribute longer term success of product to stupidity of consumers
Purchase previously scorned product for stupid relatives so they stop bothering you to help support the open source version of Apple product sold by Super Lucky Technology Extreme Inc. that you convinced them to buy
Purchase previously scorned product for yourself just to see what all the fuss is about
Admit that you now own and use the product, but complain about the product’s lack of SD card slot on random Internet forum
Forget prior criticism of product, claim that it was revolutionary and an example of how Apple used to be really innovative, but has now lost its edge
Rinse and repeat Author: The Real Blastdoor on Tue Jun 01, 2010 8:05 am
156 notes · View notes
iky1e · 13 years ago
Text
Recreating iOS6's remote views for iOS 5
If you haven't already read @olebegemann's blog post about _UIRemoteView's and remote view controllers new in iOS 6 then please do so now and come back to this after you have finished it.
http://oleb.net/blog/2012/10/remote-view-controllers-in-ios-6/
  When I first read this post about iOS 6 and _UIRemoteView's which allowed apple to move things like email into different processes and still display them as if they where in the app there was one point I that caught my attention more then it would most peoples.
<_UIRemoteView: 0x1e05c300; frame = (0 0; 320 480); transform = [0.5, -0, 0, 0.5, -0, 0]; userInteractionEnabled = NO; layer = <CALayerHost: 0x1e05c460>>
CALayerHost, the instant I sure that I thought, "wow, Apple finally put it to good use'. From my experiments with CardSwitcher I have come across CALayerHost's before. They are actually how CardSwitcher's live views work. More then displaying part of an app, however, they also allow interaction through to that app (although that is buggy iOS 5, haven't tested 6 yet). For CardSwitcher to use them as live views into apps it actually has to block interaction, if you remove that you get this http://www.youtube.com/watch?v=1D1NyXITjI0.
An individual CALayerHost will display 1 UIWindow so to display an entire app you need to have multiple CALayerHost objects and keep them in track with the apps windows, if it creates one so do you. This is a lot of, very simple, but, effectively all, boiler plate code. And so, in SpringBoard there is a class called SBAppContextHostView which houses them all as sublayers and lets you just deal with one object. (actually tracking the contexts used to be done by it itself but is now done by a separate SBAppContextHostManager object in iOS 5+). This is used for things such as the zoom effect when you close an app, and the when you open the app switcher and it slides the "app" up (in reality the context view is activated and moved instead).
But, despite the the fact it is only used by SpringBoard it is actually part of QuartzCore, which all apps link against. From my experiments I believe they have changed it's behaviour slightly in iOS 6 (to get this working well) but it should still be possible to replicate on iOS 5.
iOS 5 does have XPC I believe (it has a private XPCObjects.framework) but I haven't used it before and as I was trying to hack this together quickly didn't use it. Another thing I would do if writing this properly is what apple has done, create a proper UIRemoteViewController to handle it all and create a few protocols and helper objects either side.
To build my example app I used CPDistributedMessagingCenter to communicate between different processes. The different parts involved in my test setup are:
a library which houses my KHRemoteView (so multiple apps potentially link against it); 
the client app, this displays the remote view after 5 seconds (so you see a change);
the server app, this is what is displayed inside the other app;
a tweak running inside SpringBoard, to launch the app;
A few more notes on CALayerHost, it doesn't respect.... most things. If you set it's frame it'll take into account it's position but ignore the set size. It will always display full size. It ignores contentSize and displays 1 pixel per point (massive version of the target app). One of the few things it does respect though is it's transform, so you can use this to scale it done by the devices contentScale.
self.layerHost = [[objc_getClass("CALayerHost") alloc] init]; self.layerHost.anchorPoint = CGPointMake(0,0); self.layerHost.transform = CATransform3DMakeScale(1/[UIScreen mainScreen].scale, 1/[UIScreen mainScreen].scale, 1); self.layerHost.bounds = self.bounds;
Another annoying thing is that it seems to fight with SpringBoard. All windows have a corresponding SBContext and CALayerHost in SpringBoard. What I think is happening is that when we set the contextId for the layerHost it becomes the host layer for that context. However the SpringBoard one then takes back control of the context the next render, possibly because SB is the render server (below iOS 6) and it is automatically given priority or it updates each pump of the runloop. Even though it loses the link with the context very quickly it still sends it touch events, you just don't see the results. To get around this I set the contextId to 0 and then instantly back to what it was 60 times a second (the devices screen refresh rate).
//... KHRemoteView.m -(void)updateDisplay{ if (update) { unsigned int contextID = self.layerHost.contextId; self.layerHost.contextId = 0; self.layerHost.contextId = contextID; [self performSelector:@selector(updateDisplay) withObject:nil afterDelay:(1/60)]; } } //...
In my demo server (Service?) app I have it display an MFMailComposeViewController (as a reference back to the original article). A few odd things with this are due to my using only one CALayerHost (I should use 2, or possible 3 for you not to notice anything. 1 for the app, one for the UITextEffectsWindow (keyboard) and another for alerts/action sheets). The copy & paste menu is in a separate UIWindow and so is not shown when you select text, but the text range selection blue bars are. The keyboard, alerts and action sheets and not that but you can still type and interact with them. The layers send touch events through not to the window but to the app itself, so if you can type without looking on iOS you should still be able to write an email with this app.
// Send messages to launch the server app and get the servers contextId... [[objc_getClass("CPDistributedMessagingCenter") centerNamed:@"com.iky1e.remoteView.sb.messaging.center"] sendMessageAndReceiveReplyName:@"kh_launch_remote_app" userInfo:nil]; // Lazy loading the library (makefiles aren't my strong point)... dlopen("/usr/lib/LibRemoteView.dylib", RTLD_NOW);
The server itself is very basic, it just displays an MFMailComposeViewController. The original one had a UIButton and a view that animated up and down, but I switched to this to show a more interactive example.
Here's a video of the basic demo application. You can see some of the weird effects, typing without a keyboard for example.
youtube
  Finally here is the code: it includes the tweak running in SpringBoard, the client app, the server app, and the library that the client links against to access the KHRemoteView class. Have a look and tell me what you think, here on HackerNews or on twitter?
https://github.com/freerunnering/libremoteview
0 notes
iky1e · 13 years ago
Link
How to code to space craft levels of safety.
Not all of this is applicable to Cocoa and Cocoa Touch development (good luck not using the heap), but so much of it is. I recommend reading the whole thing, but here are some highlights translated to Objective-C and its environs:
Rule 2 (routine checking)
All code shall always be compiled with all compiler warnings enabled at the highest warning level available, with no errors or warnings resulting.
All code shall further be verified with a JPL approved state-of-the-art static source code analyzer, with no errors or warnings resulting. …
… The rule of zero warnings applies even in cases where the compiler or the static analyzer gives an erroneous warning. If the compiler or the static analyzer gets confused, the code causing the confusion should be rewritten so that it becomes more clearly valid. Many developers have been caught in the assumption that a tool warning was false, only to realize much later that the message was in fact valid for less obvious reasons. …
Raise your hand if you’ve heard the sentence “it’s a false positive, ignore it” before.
Rule 7 (thread safety)
Task synchronization shall not be performed through the use of task delays.
Specifically the use of task delays has been the cause of race conditions that have jeopardized the safety of spacecraft. The use of a task delay for task synchronization requires a guess of how long certain actions will take. If the guess is wrong, havoc, including deadlock, can be the result.
In Cocoa/Cocoa Touch, this means that you should avoid using performSelector:withObject:afterDelay: (or sleep, usleep, nanosleep, +[NSThread sleepForTimeInterval:], -[NSRunLoop runUntilDate:], etc.) to try to “fix” a bug. Occasionally it fixes something. Often it breaks something else. And often it doesn’t fix the original problem.
For instance, an area of memory above the stack limit allocated to each task should be reserved as a safety margin, and filled with a fixed and uncommon bit-pattern.
On the Mac, you can do this with the malloc environment variables and/or GuardMalloc.
Rule 15 (checking parameter values)
The validity of function parameters shall be checked at the start of each public function.
The validity of function parameters to other functions shall be checked by either the function called or by the calling function.
Foundation provides NSParameterAssert for this purpose. In Objective-C, what this document calls a “public function” will generally be a method you’ve declared in the @interface in your class’s header file, whereas other functions are methods that you haven’t declared there. In other words, the class should trust itself to give itself good input, but not other classes.
Test cases are a good way to exercise these assertions: Intentionally send messages to the class, or instances of it, with bad input, knowing that if the assertion fails (an exception is thrown), the test will fail. If that doesn’t happen, it may indicate that the bad input would spread deeper into the class/object in a real run, which could be causing a problem your users are seeing (or will see).
Rule 25
Functions should be no longer than 60 lines of text and define no more than 6 parameters.
This is especially true of C functions, since there’s nothing to label the parameters at the call site, but it’s a good rule for Objective-C, as well. If a single message contains more than, let’s say, 4 arguments, I recommend building an object around that message instead. Turn the arguments, particularly any that are optional, into properties.
Such objects will probably help you clarify other aspects of your design while you’re at it.
9 notes · View notes
iky1e · 13 years ago
Text
Check
If you are a heavy email user you will likely have noticed in iOS's default mail app you have to select each and every email separately, so if you want to select lots, say 30 emails, you have to scroll through the list selecting each and every one. Check allows you to just tap and hold on an email and then scroll as far as you like before tapping another. Everything between those 2 emails will be selected (or deselected) automatically.
The idea was originally Joshua Tucker's and he planned out the details, like the flashing animation to show which is the start point, and then I worked out how to implement them. 
http://www.idownloadblog.com/2012/07/09/check/
http://www.addictivetips.com/ios/check-batch-select-multiple-items-in-ios-mail-with-a-single-touch/
5 notes · View notes
iky1e · 13 years ago
Text
MountainCenter
I recently released a joint project with Jonas Gessner called MountainCenter, it was inspired by MountainLion's implementation of NotificationCenter which has the notification center appear from under the right hand side of the screen.
It also has a smooth dragging gesture from the edge of the screen to drag it over and reveal the notification center underneath.
http://www.idownloadblog.com/2012/06/23/mountain-center-cydia/
http://modmyi.com/content/8045-mountaincenter-makes-notification-center-ios-react-like-os-x-mountain-lion.html
3 notes · View notes
iky1e · 13 years ago
Video
youtube
I’ve been working on a way to make text editing on iPad better. I’ll fill out more of my thoughts on the subject later, but for now you can get the gist from the video! Make sure you follow the directions in the youtube video description if you want these features for yourself.
45 notes · View notes
iky1e · 13 years ago
Text
chpwn:
The “dickbar” (as Gruber puts it) may be the big news item lately, from my “Twizzler” to remove it to the various websites springing up about it. But, this post is about something much more mundane and technical in Twitter for iPhone: sliding headers for UITableView.
When you first open Twitter for iPhone, you get this screen. Looks like just a standard UITableView and a custom -tableHeaderView set, yeah? Not quite. There’s actually an interesting effect here: when you scroll, the header actually slides under the table view. If that didn’t make sense (and it’s not a good explanation, sorry) I’ve uploaded a video that demonstrates the effect:
Read More
Very nice, 
Sliding UITableView Header Views
13 notes · View notes
iky1e · 14 years ago
Text
Current Projects: Understanding iOS' App Rendering
For the last 2 months almost all my work has been on reversing how iOS displays apps on screen. There are a few ways to get the display information and pass touch events down to the application. Currently I'd like to think I understand about 80-90% of how SpringBoard manages and displays apps.
For instance, when the App Switcher launches it doesn't move the applications window 'up' as it looks like visually but rather displays a view that is rendering the applications SBContext's instead of it. That is then moved up so the application itself is not involved (why if you check the window's frame of an application it doesn't change with the app switcher's opening and closing.
Once the iPad is jailbroken I'll start writing this up into an actual tweak, mostly for iPhone apps on iPad (but it's big enough for multiple iPad apps on screen too). Also once I'm confident I understand iOS's app rendering fully I plan to release my notes on it all.
CardSwitcher
I've also been rewriting CardSwitcher and to put more thought into the API's design, the first one wasn't designed to do more then the WebOS style interface mode and the UI & data stuff where horrible interlinked.
My work on understanding how iOS displays things also means I have a new faster, better & just generally much improved way to get screenshots of the apps (unlike multifl0w which uses UIGetScreenImage() this method won't capture the app switcher if it's open, for example). And I can also now have a live view of any currently running apps (open or backgrounded with backgrounder) rather then a static image. Another small improvement is pausing the application when entering CardSwitcher, like the app switcher does. By pausing I don't mean suspending but informing the app that the appswitcher is open and so games should open the pause menu, ext.
I hope to have these projects finished and released soon(-ish). (though this likely means longer then I think, as is always the case when a developer says they are almost done)
8 notes · View notes
iky1e · 14 years ago
Text
Code Snippet: Launch apps on iOS5
I've been working with the SBDisplayStack's lately and trying to control how apps launch and finally got it working, much more simply then a was trying originally.
The finished code has been put together into an opensource library on GitHub called LibDisplay.
One odd thing that caught me out, for ages, is you have to start launching the next app before getting rid of the current one.
/* References: * http://iky1e.tumblr.com/post/13985531616/raw-log-sbdisplay-settings * http://iphonedevwiki.net/index.php/SBDisplay * http://iphonedevwiki.net/index.php/SBDisplayStack * http://code.google.com/p/iphone-tweaks/wiki/DevelopmentNotes */ -(void)activateApplication:(SBApplication *)toApp animated:(BOOL)animated{ // Get the currently open application. SBApplication *fromApp = [self topApplication]; // Check if it's the same as the currently open application, if it is there's nothing todo. if ([[toApp displayIdentifier] isEqualToString:[fromApp displayIdentifier]]) return; // If animated they want the system default (app to app transition, or zoom on homescreen). if (animated && toApp) { [(SBUIController*)[objc_getClass("SBUIController") sharedInstance] activateApplicationFromSwitcher:toApp]; return; // Done, wasn't that easy. } // Now, if we were asked to, open the other app. if (toApp) { [toApp clearDisplaySettings]; [toApp clearActivationSettings]; [toApp clearDeactivationSettings]; // 20 = appToApp [toApp setActivationSetting:20 flag:YES]; // Note if it's a large application the user might see a brief flash of the homescreen. [[self SBWPreActivateDisplayStack] pushDisplay:toApp]; } // If another app is open then close it if (fromApp) { // Clear any animation settings the app may have [fromApp clearDisplaySettings]; [fromApp clearActivationSettings]; [fromApp clearDeactivationSettings]; // Now pop is from the Active displayStack [[self SBWActiveDisplayStack] popDisplay:fromApp]; // And push it onto the Suspending displayStack [[self SBWSuspendingDisplayStack] pushDisplay:fromApp]; } if (!toApp) { // The user should now be on the homescreen. // There's a bug above 4.? (4.1 or 4.2 I think) where the status bar won't be there. SBUIController *uiController = (SBUIController*)[objc_getClass("SBUIController") sharedInstance]; if ([uiController respondsToSelector:@selector(createFakeSpringBoardStatusBar)]) { [uiController createFakeSpringBoardStatusBar]; } } }
A few notes about this:
This info is "as of" iOS 5.0.1 and I can only confirm that it works on iOS 5.x.
although, Multifl0w pushes the displaystacks around itself and worked without modification (to the best of my knowledge) when iOS 5 was released (so it might not break very often).
When closing an app without an animation SpringBoard will still animate the icons unscattered (there's almost certainly a work around but I haven't needed to look for it).
7 notes · View notes
iky1e · 14 years ago
Text
raw log: SBDisplay Settings
This is how SpringBoard describes it's activation settings (there might be more but I stopped when it stopped telling me things).
Activation Setting
cy# [app descriptionForActivationSetting:1] "asPanel " cy# [app descriptionForActivationSetting:2] "suspended " cy# [app descriptionForActivationSetting:3] "URL " cy# [app descriptionForActivationSetting:4] "remoteNotification " cy# [app descriptionForActivationSetting:5] "localNotification " cy# [app descriptionForActivationSetting:6] "eventOnly " cy# [app descriptionForActivationSetting:7] "safe " cy# [app descriptionForActivationSetting:8] "animateOthersSuspension " cy# [app descriptionForActivationSetting:9] "didAnimateOthersSuspension " cy# [app descriptionForActivationSetting:10] "slideOthersSuspension " cy# [app descriptionForActivationSetting:11] "flipOthersSuspension " cy# [app descriptionForActivationSetting:12] "contextInfoForOthersSuspension " cy# [app descriptionForActivationSetting:13] "animateScaleForOthersSuspension " cy# [app descriptionForActivationSetting:14] "animationStartForOthersSuspension " cy# [app descriptionForActivationSetting:15] "animationStart " cy# [app descriptionForActivationSetting:16] "flip " cy# [app descriptionForActivationSetting:17] "animationDuration " cy# [app descriptionForActivationSetting:18] "animationDurationForOthersSuspension " cy# [app descriptionForActivationSetting:19] "firstLaunchAfterBoot " cy# [app descriptionForActivationSetting:20] "appToApp " cy# [app descriptionForActivationSetting:21] "activateFromLocked " cy# [app descriptionForActivationSetting:22] "originatingURLDisplayIdentifier " cy# [app descriptionForActivationSetting:23] "annotation " cy# [app descriptionForActivationSetting:24] "noAnimate " cy# [app descriptionForActivationSetting:25] "launchOptions " cy# [app descriptionForActivationSetting:26] "withNoZoomLayerSetting " cy# [app descriptionForActivationSetting:27] "launchImageName " cy# [app descriptionForActivationSetting:28] "fromSwitcher " cy# [app descriptionForActivationSetting:29] "shouldUnlockOrientationForSwitcherSetting " cy# [app descriptionForActivationSetting:30] "viaSlideTopAppToReveal " cy# [app descriptionForActivationSetting:31] "fromBanner " cy# [app descriptionForActivationSetting:32] "fromBulletinList " cy# [app descriptionForActivationSetting:33] "fromAssistant "
Deactivation Setting
cy# [app descriptionForDeactivationSetting:1] "eventOnly " cy# [app descriptionForDeactivationSetting:2] "animate " cy# [app descriptionForDeactivationSetting:3] "slide " cy# [app descriptionForDeactivationSetting:4] "animationStart " cy# [app descriptionForDeactivationSetting:5] "forceExit " cy# [app descriptionForDeactivationSetting:6] "afterNextLaunch " cy# [app descriptionForDeactivationSetting:7] "flip " cy# [app descriptionForDeactivationSetting:8] "contextInfo " cy# [app descriptionForDeactivationSetting:9] "animationScale " cy# [app descriptionForDeactivationSetting:10] "returnToLastApp " cy# [app descriptionForDeactivationSetting:11] "startForOthersActivation " cy# [app descriptionForDeactivationSetting:12] "killed " cy# [app descriptionForDeactivationSetting:13] "underLock " cy# [app descriptionForDeactivationSetting:14] "animationDuration " cy# [app descriptionForDeactivationSetting:15] "durationForOthersSuspension " cy# [app descriptionForDeactivationSetting:16] "deactivateAnimateOthersResumption " cy# [app descriptionForDeactivationSetting:17] "suspensionAnimationDelay " cy# [app descriptionForDeactivationSetting:18] "disableIconUnscatterAnimation " cy# [app descriptionForDeactivationSetting:19] "slideStatusBarStyleSetting " cy# [app descriptionForDeactivationSetting:20] "deactivateFromSwitcherSetting " cy# [app descriptionForDeactivationSetting:21] "zoomAnimateOtherOnResume " cy# [app descriptionForDeactivationSetting:22] "displayFenceTeardown " cy# [app descriptionForDeactivationSetting:23] "orderOutOnlyIfOnTop " cy# [app descriptionForDeactivationSetting:24] "viaSystemGesture " cy# [app descriptionForDeactivationSetting:25] "crossfade "
Display Setting
cy# [app descriptionForDisplaySetting:1] "finishedLaunchingFrontmost " cy# [app descriptionForDisplaySetting:2] "resume " cy# [app descriptionForDisplaySetting:3] "animate " cy# [app descriptionForDisplaySetting:4] "animateNoPNG " cy# [app descriptionForDisplaySetting:5] "statusBarStyle " cy# [app descriptionForDisplaySetting:6] "statusBarOrientation " cy# [app descriptionForDisplaySetting:7] "statusBarHidden " cy# [app descriptionForDisplaySetting:8] "statusBarWindowContextId " cy# [app descriptionForDisplaySetting:9] "arguments " cy# [app descriptionForDisplaySetting:10] "environment " cy# [app descriptionForDisplaySetting:11] "standardOut " cy# [app descriptionForDisplaySetting:12] "standardError " cy# [app descriptionForDisplaySetting:13] "waitForDebugger " cy# [app descriptionForDisplaySetting:14] "userLaunch " cy# [app descriptionForDisplaySetting:15] "disableASLR " cy# [app descriptionForDisplaySetting:16] "launchOverSEOAppSetting " cy# [app descriptionForDisplaySetting:17] "launchedViaSystemGesture "
8 notes · View notes
iky1e · 14 years ago
Text
raw log: SpringBoard closing an app (in a hurry)
I had written a little method to open and close apps for me so I could do quicker then just 0.5 second animations (the app switchers speed). I wrote it from a mixture of logging the description of different SBDisplay methods (the "-(NSString*)descriptionFor*****Setting:(unsigned)number" one's) and this (though it doesn't work on iOS 4+5). 
I wanted to know how iOS closes an app without an animation as that's the only thing I had left not working and this is what I got when I logified the interesting methods in SBDisplay and "-(void)kill"ed and app.
Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ setDeactivationSetting:12 flag:1] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ accelerometerDeviceOrientationChangedEventsEnabled] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ accelerometerSampleInterval] Dec 9 22:07:30 Kyles-iPod com.apple.launchd[1] (UIKitApplication:com.apple.weather[0x7dca][210]): (UIKitApplication:com.apple.weather[0x7dca]) Exited: Killed: 9 Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: Application 'Weather' exited abnormally with signal 9: Killed: 9 Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ setActivationSetting:2 flag:0] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ clearDisplaySettings] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ exitedAbnormally] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ _exitedCommon] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ clearActivationSettings] Dec 9 22:07:30 Kyles-iPod SpringBoard[15]: -[ clearDeactivationSettings]
3 notes · View notes
iky1e · 14 years ago
Text
SpringBoard Icon Layouts - IconState.plist
I was looking for a way to get a list of all applications, that aren't hidden (so excluding things like Web.app). And although I found it ((NSArray*)[[SBIconModel sharedInstance] visibleIconIdentifiers]). I also found a dictionary SpringBoard keeps of the Icon layout.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>buttonBar</key> <array> <string>com.apple.MobileSMS</string> <string>com.apple.mobilemail</string> <string>com.apple.mobilesafari</string> </array> <key>iconLists</key> <array> <array> <string>com.apple.mobilephone</string> <string>com.apple.mobilecal</string> <string>com.apple.mobileslideshow</string> <string>com.apple.camera</string> <string>com.apple.videos</string> <string>com.apple.youtube</string> <string>com.apple.Maps</string> <string>com.apple.weather</string> <string>com.apple.mobilenotes</string> <string>com.apple.reminders</string> <string>com.apple.mobiletimer</string> <string>com.apple.gamecenter</string> <dict> <key>displayName</key> <string>Apple</string> <key>iconLists</key> <array> <array> <string>com.apple.mobileme.fmf1</string> <string>com.apple.Cards</string> <string>com.apple.iBooks</string> </array> </array> <key>listType</key> <string>folder</string> </dict> <string>com.apple.MobileStore</string> <string>com.apple.AppStore</string> <string>com.apple.Preferences</string> </array> <array> <dict> <key>displayName</key> <string>Utilities</string> <key>iconLists</key> <array> <array> <string>com.apple.MobileAddressBook</string> <string>com.apple.calculator</string> <string>com.apple.VoiceMemos</string> </array> </array> <key>listType</key> <string>folder</string> </dict> <dict> <key>displayName</key> <string>Jailbreak</string> <key>iconLists</key> <array> <array> <string>com.saurik.Cydia</string> <string>libactivator</string> <string>eu.heinelt.ifile</string> <string>crash-reporter</string> <string>com.googlecode.mobileterminal.Terminal</string> </array> </array> <key>listType</key> <string>folder</string> </dict> <dict> <key>displayName</key> <string>Social</string> <key>iconLists</key> <array> <array> <string>com.atebits.Tweetie2</string> <string>info.colloquy.mobile</string> <string>com.tapbots.Tweetbot</string> </array> </array> <key>listType</key> <string>folder</string> </dict> <dict> <key>displayName</key> <string>Other</string> <key>iconLists</key> <array> <array> <string>com.apple.stocks</string> <dict> <key>displayName</key> <string>Newsstand</string> <key>iconLists</key> <array/> <key>listType</key> <string>newsstand</string> </dict> </array> </array> <key>listType</key> <string>folder</string> </dict> <string>com.clickgamer.AngryBirds</string> <string>com.apple.mobileipod</string> </array> </array> </dict> </plist>
Lets take a closer look at this:
the dock icons are in a separate array for key 'buttonBar';
the pages are in the array for key 'iconLists';
each page is a separate array in the iconLists array;
in the array for each page the icons are string;
the icons string is the apps displayId;
a folder is an NSDictionary;
each folder has these keys;
a displayName key which is a string, it's name;
iconLists which is an array of icons like each pages (displayId strings);
To make a change to the icon-state do:
[[SBIconModel sharedInstance] _writeIconState:modifiedIconState toPath:[[SBIconModel sharedInstance] iconStatePath]]; // And then to actually have it update the icons [[SBIconModel sharedInstance] noteIconStateChangedExternally];
All the relevant methods are in the SBIconModel.h file. (warning though you can mess up your layout by playing with this.)
15 notes · View notes
iky1e · 14 years ago
Text
Tutorial: Cool UIScrollView Effects
While I was working on the "Cardflow" interface mode for CardSwitcher I had to work out get custom page widths and custom effects as you scroll through the cards, this is actually quite simple but I haven't seen many posts on customising a UIScrollView. Most of the tips are spread across lots of different stackoverflow questions.
Problems with custom scrollview's
To start with (actually while I was working on the first version of CardSwitcher) I looked into iCarousel, which has quite a lot of cool effects and a tableView style data source and delegate protocols. However as the first version of CardSwitcher was actually just a standard WebOS, or Safari tab's style, linear layout that highlighted a problem with iCarousel (which joehewitt also noticed with iScroll), caused by the fact it doesn't customize a UIScrollView but instead uses UIGestureRecognizers to do the scrolling itself (like UIScrollView itself).
However because of this the scrolling just feel wrong, the physics are off by a little bit. The bounce as you scroll of the edge, flicking and then how many pages it scrolls past before stopping and the paging effect all just feels off slightly.
When using iCarousel for the purpose it was designed for, the coverflow or other custom modes, and you might not notice. However as CardSwitcher would have used the linear mode only, at least for the initial release, that would annoy me. For instance Multifl0w's 'cards' style has a custom scrolling too, it feels very smooth but isn't quite right still.
So after explaining why I didn't like using a custom methods I'll now point out why people feel a need to develop these custom methods rather then using a UIScrollView.
The most obvious problem is "paging". To activate paging on a UIScrollView you just set it's pagingEnabled property to YES. However it defaults to each page being the same width as the scrollview itself, meaning if you want to achieve a preview effect like in Safari (screenshot below) you can't do it by simply specifing a custom page width.
Also the custom scrollview's all have built in ways to create custom effects whereas UIScrollView provides no built in way to achieve cool effects, so you'll have to work it out yourself.
Despite the need to subclass and customize the UIScrollView yourself it's is a very refined and very well built UIKit class and over all I think it's best to just deal with the one or 2 limitations then throw it all away and start again from scratch or use a custom scrollview library. The difficulty of matching the refinement of a UIScrollView is highlighted well by the numerous JavaScript libraries which try to mimic it for web apps and the native attempts at making custom scrollviews (none of which get the physics quite right).
Customizing UIScrollView & Adding Effects
So now to the fun bit (the code). Customizing the page width of a UIScrollView is actually quite simple, set the width to whatever you want and then set the 'clipsToBounds' property to NO, very simple. Except it's not quite that simple as there's a little problem with that (how big a problem depends on how small you want to the page widths to be). The problem is that touches will only be received inside the view's bounds. So if your use for this is a scrolling menu (like a UITableView) that's page width is the width of one cell only the center one will receive touches. To fix that you need to subclass UIScrollView and override the -(BOOL)pointInside: withEvent: method.
@interface CustomScrollView : UIScrollView @property (nonatomic, assign) UIEdgeInsets responseInsets; @end @implementation CustomScrollView - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { CGPoint parentLocation = [self convertPoint:point toView:self.superview]; CGRect responseRect = self.frame; responseRect.origin.x -= self.responseInsets.left; responseRect.origin.y -= self.responseInsets.top; responseRect.size.width += (self.responseInsets.left + self.responseInsets.right); responseRect.size.height += (self.responseInsets.top + self.responseInsets.bottom); return CGRectContainsPoint(responseRect, parentLocation); } @end
Though for CardSwitcher I use a less flexible implementation because it does what I want.
@implementation CustomScrollView - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { CGPoint parentLocation = [self convertPoint:point toView:self.superview]; return [self.superview pointInside:parentLocation withEvent:event]; } @end
This now means that no matter how small the scrollview (in Cardflow mode it's only 30px wide) you'll still be able to scroll by dragging anywhere on it's parent view.
Cool Effects
Now we're going to go through and create a few cool scrolling effects.
Now I actually have each card keep track of it's offset and set it's own transform but you can easily do this in a for loop in the scrollViewDidScroll delegate method if you want. Note though that you'll need a way to track the index of each card (hopefully besides just using it's position in the UIView's subviews).
// Method that get's called every time the scrollView scrolls. -(void)setTransform{ /// setting up zoom effect!!!!!! UIScrollView *scrollView = //get the scrollView (most likely either self.scrollView or self.superView); // Set the layers transform back to normal so it's frame wouldn't be effected while we do the calculations self.layer.transform = CATransform3DIdentity; // Easier reference to these CGFloat scrollViewWidth = scrollView.bounds.size.width; CGFloat offset = scrollView.contentOffset.x; // Do some initial calculations to see how far off it is from being the center card CGFloat pageIndex = ([/* an array (hopefully not self.superviews.subviews)*/ indexOfObject:self]); CGFloat currentPage = (offset/scrollViewWidth); CGFloat pageDifference = (pageIndex-currentPage); // And the default values CGFloat scale = 1.0f; CGFloat alpha = 1.0f; /*** NOW FOR THE EFFECTS ***/ // Scale it based on how far it is from being centered scale += (pageDifference*0.2); // If it's meant to have faded into the screen fade it out if (pageDifference > 0.0f) { alpha = 1 - pageDifference; } // Don't let it get below nothing (like reversed is -1) if (scale < 0.0f) { scale = 0.0f; } // If you can't see it disable userInteraction so as to stop it preventing touches on the one bellow. if (alpha <= 0.0f) { alpha = 0.0f; self.userInteractionEnabled = NO; } else{ self.userInteractionEnabled = YES; } /*** Set our effects ***/ self.alpha = alpha; // We could do just self.transform = but it comes by default with an animation. [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; self.layer.transform = CATransform3DMakeScale(scale, scale, 1.0f); [CATransaction commit]; }
This will create the same effect as the 'Cardflow' mode in CardSwitcher. However the important bit's are those initial variables and then the end bit where you set it's transform. In between you can fiddle with those values to create the cool effects.
If you want some examples of cool scrollView effects have a look at the iCarousel Demo project, which includes these effects: Linear, Rotary, Inverted Rotary, Cylinder, Inverted Cylinder, CoverFlow, CoverFlow2 and a Custom one similar to this one.
If you have any questions or comments please post them below.
11 notes · View notes