Can you update this to work with Xcode 5? For some reason it won't let me build against the SDK.
Thx,first.
I run your code, in my prj. Some error comes up for webview didnot load html file before invoking it.
So I add some code below:In -[logData:file:lineNumber:]
if (![webView isWebViewLoaded]) {
return;}
In NSLogConsoleView - (BOOL)isWebViewLoaded;
I have used tail -f /NSLog.txt command in terminal, which made my XCode console doesn't show any log. I want to roll back and make my console work properly as earlier.
Can any one tell us command to roll back this.
You can also extend CALayer with a new class that implements this. Sadly your site doesn't allow me to post code so here's my best description:
Override CALayer.defaultActionForKey and return a nil for key = 'sublayers'.
I used this approach in a recent release of my app, and I have to say — whilst it's quite clever, it blows out memory usage significantly due to the JS JIT compiler and other things being hosted in your app's memory space. If you don't have concerns about memory, this is a nice, simple approach — otherwise, I think you're better off finding something built on top of the simple POSIX regex tools.
@dvbfreaky : JSObjectMakeArray
takes a C array as parameter. Allocate one and put your values in it :
JSValueRef* values = malloc(sizeof(JSValueRef)*itemCount);
array[0] = JSValueMake(...)
array[1] = ....
JSObjectRef jsArray = JSObjectMakeArray(ctx, itemCount, values, NULL);
free(values)
Hi, please teach me, how to convert char* - string to JSArray Object.
char* -> JSStringRef . JSSTringRef->JSValueRef . JSValueRef ->JSValueMakeArray. Does not help. becase JSValueMakeArray need jsValue array as 3rd argument. Any help appreciated..
dvbfreaky007@gmail.com
Thanks for this wonderful peace of code. While testing I found that -init of NSLogConsole is called twice: 1st by NIB-Loader and 2nd by -sharedConsole.
You can. This post is an offshoot of exploring AppleScript, how it actually makes for (I think) simpler design even when not using it.
I haven't tried it, but can't you just bind to NSApp with a key path of @"delegate.myCustomKey"
? No containers needed that way for longer key paths.
Thanks. Would have been better if you could provide more explanation and complete examples.
A quick bench shows the get accessor 3% slower than valueForKey: and a set/get couple being 20 times slower.
For the problem about Xcode complaining about non existant methods, just create a interface for a category on the class declaring the methods but don't implement category. Xcode will see the declarations
On a separate issue do you have any experience with performance. How much overhead does this create. Eg. Time to make 10000 accesses on this as opposed to just using objectForKey: and setObject:forKey:
I have done something similiar in creating acccessors at runtime by adding methods to a class that all route their implementation to a single c function that parses the selector to handle the actual data accesses. Being written in c I have sense is that it is only a minor overhead. I'll post this later as I have time. (btw. A good deal of credit for this technique goes to Jeff Lamarche.)
Actually, that behaviour is all over Mac OS X :-)
E.g. (after activating Desktop Exposé)
Ah, I didn't try the scaling yet. Good to know it's also useful there.
(& thanks for the bug report !)
Yeah, affine clamp is your friend! We use it in Sandvox for scaling images so that the scaled images have opaque edges - otherwise the fractional edge pixels will be translucent. Similar to the above transform and blurring issue.
(BTW, your blog commenting input system is not handling HTML entities properly... if one tries to enter an ampersand here, the comment will be rejected.)
Thanks for this great introduction. There is precious little info on how to use the JavaScriptCore API.
Thanks for posting this. It's a nice to be able to see a complete gradient example put together in such a compact, straightforward way.
Yes, I'm following the Objective-J and JSTalk route.
Extending Javascript this way seems like a good idea.
This looks remarkably like the Objective-J code used for the Cappuccino framework. Are you doing something similar?
A good list. You missed the concurrency options on the Foundation collections enumeration methods though, which some will find very convenient.
NSDictionary's enumeration methods provide an additional convenience; it passes both the key and the value for every entry in the dictionary. No more enumerating over the keys, then getting the values separately.
NSIndexSet also has a very useful enumeration method now. No more need to use the awkward -firstIndex and -indexGreaterThanIndex: approach.
There are also two NSString methods: enumerateSubstringsInRange:options:usingBlock:, which will let you enumerate lines, paragraphs, composed character sequences, words, or sentences, and the convenience method, enumerateLinesUsingBlock:.
Also, you have an error in #4. obj1-obj3 need to be __block variables. Otherwise, the block just captures the pointer values at the point where it is created.
You're welcome ! That's the sort of thing you can stumble upon when playing around with F-Script. It will let you explore all Cocoa classes and methods at runtime.
Great information, just what I've been looking for, for two days, night all over the net! You may want to add the following to one of your include-files...
@interface NSWindow (private) - (void)setBottomCornerRounded:(BOOL)aFlag; @end
...to avoid the compiler-warning and get a nice build.
Patrick, you are a genious! :)
It's exactly what I've been looking for. -And I would probably not have found it without your help, as it seems it's a private API - it gives me a compiler warning that NSWindow may not respond to it, but I just checked that it respondsToSelector:@selector(setBottomCornerRounded) and I got a YES. =)
It's probably also far better than my 6 year old solution, thankyou a billion!Jens, you're looking for NSWindow's setBottomCornerRounded.
http://parmanoir.com/NSWindow_goodies_:_bottomCornerRounded,_usesLightBottomGradient
Great snippet!
I'm searching for a way to make the two bottom corners of a textured window have 'sharp' or 'square' corner like Safari, as I want a status bar down there. I once found out around 7 years ago, but I lost that snippet.
My solution was done when the window was initialized somehow, it didn't use more than 1 or 2 lines, but as I recall it, it didn't seem clear that it should/could be done this way.I believe that I made a window in IB, then when loaded, I changed it from non-textured to textured, while I also changed some styling or something similar.
Do you by any chance know how to do this?
Very nice example ! Thanks a lot. Apple should provide that as sample code for CATextLayer.
You can also use object_getClass(self) to return either the class or metaclass depending on wether self is an instance of a class or metaclass respectively.
Neat stuff. I don't think I'd have found this on my own. I think it's ok for some button styles, but I wonder if there's a way to tweak it so it doesn't color the grey pixels around anti-aliased text. Thanks for sharing.
You're welcome !
I just tried darkening the window, it quickly looks very dark. You might have to draw the title and the toolbar labels yourself.
Cool tip! I was going to look into doing something like this for the app I'm working on to experiment with giving it a bit of a darker look. Not sure if it'll look good or just weird yet though, it's a fine line between giving an app a unique style and just messing with things that are already good. This technique seems easy enough to quickly find out though.
Thanks for sharing a way of doing it!
I guess it's possible. I wanted to draw over the existing frame, letting it handle drawing of buttons, toolbar, resize container, etc. Replacing the frame would mean I'd have to do it, and that's too much work ;)
can't you just replace the themeview with your own object? i mean, the NSWindow somehow sets this object, so i'm sure you can simply replace it. i guess you don't need to method swizzle NSThemeFrame, but instead create your subclass of NSThemeFrame and use that instead. I've just had a look. there's a _borderView instvar in NSWindow which keeps this theme frame so it could work if you change it, but i'm sure you'd need to do some housekeeping as well. like setting up the view in the window properly and such stuff...
Karsten
Ah indeed when I move the view on the side to be clipped by the window, redrawing is incorrect. Adding rect = [self bounds]
before Scale down drawing rect fixes the issue. Thank you !
The rect
is the dirty rectangle that needs redrawing. When you resize the window and the view, the whole view needs updating.
However, a part of the view can also be chosen to redraw, through use of methods such as:
- (void)setNeedsDisplayInRect:(NSRect)invalidRect
The invalidRect
argument is then the rectangle used in the -drawRect:
method. (Or if further rectangles are specified later, then a union of all those rectangles.)
By only invalidating what has changed, and then by drawing only what has been invalidated, your drawing becomes more efficient.
Picture where the user is working on some sort of elements in a view, such as selecting a range of text in a text view, or rolling their mouse over a list of buttons and having them highlight. Only a portion of the view is changing and needing to be redrawn.
If you launch the 'Quartz Debug' utility that shipped with your developer tools, you can enable options to flash, or highlight, the areas that are being updated on screen. You'll see that Apple are usually pretty efficient with the amount they redraw.
So coming back to the first point, since using rect
is inappropriate, you should use -[NSView bounds]
for finding the actual size of the view (in its drawing space).
Apply has a guide on efficient view drawing if you want more information.
I'm not noticing any difference between rect and [self bounds] ? What's it supposed to do ?
A small niggle. Instead of using the rect
argument, which is the region that needs updating, you should ask for the view's bounds.
NSRect bounds = [self bounds]; // Now use this for the full width and height.
So that explains the Ruby overexposure. I didn't expect it static languages to be that low. C+Java+C++ = 6% !
Also, you'll find that those languages have a much more active open source community that have adopted modern collaboration tools like GitHub. Much more say than a mailing list oriented community like Cocoa.
It's a matter of who is using the site. The reason for the popularity of dynamic languages in Github is the people using it. The site was created in Ruby on Rails (though I believe Erlang is used in its backend as well) and I believe the Rails team is using Github as the repository for Rails. Plus, early on, the RoR world embraced Git as their SCM of choice, hence the popularity of Ruby, in particular. Because of this history, Github has become the darling of the startup oriented, web application development population, and so, languages that are most popular for developing web applications are going to be the most popular on Github.
At least, that's my theory anyway :-)
Thanks for the link ! As dup2 does redirect all stderr, it's really quite blunt.
I like that NSLog
prints both in Xcode and in the console — opening Console. app is a quick and easy way to see if/where your app failed, so I'm all in favor of NSLog
, debug or release :)
That doesn't strike me as the best way. All stderr output will go to the file in that case. That might not be optimal.
I used the following code to enable NSLog on the early iPhone betas (when NSLog was broken):
http://code.google.com/p/touchcode/source/browse/trunk/Experimental/Deprecated/TouchDebugging.m
(Not sure who I got the original code from - Jens maybe?)
It's my opinion that NSLog shouldn't exist in a non-debug app - you should be logging via a different mechanism (asl springs to mind). But these techniques are good as work arounds.
Thanks !
I've always felt the title bar was underused. All that space for a tiny bit of text … that's a shame :)
Nice diagram! Very pretty.
I don't know if I would ever put a help button there in my own program but it's fun to see people try things just because it can be done.
Tooting my own horn: try HoudahSpot.
"File name" "ends with" ".jscocoa"
Save as template
Does passing arrays from JS to ObjC work for you? If I try it, I get a WebScriptObject instead of an NSArray (even though the docs say it's supposed to work).
It would be interesting to see how they all look with syntax highlighting - that helps remove some of the visual noise in XML.
> Their answer was: this is by design, do not rely on app exiting from UIApplicationMain, the place to do cleanup is applicationWillTerminate: and nowhere else.
Hahaha ! What an answer ! :)
> I'm also not convinced creating and deallocating a global pool from an arbitrary point within your program flow really works. IMHO ugly things happen if you release a pool down in the stack while others are still on top.
Yes, this is ugly. I'll most likely create my JSCocoaController
later in the code.
Regarding what happens, we can look at the gnustep code : http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSAutoreleasePool.m?rev=26258&view=markup — releasing one pool deallocates all its children. Maybe the Apple runtime works the same way. In any case, it doesn't crash and does kill all objects.
iPhone app templates already have that global autorelease pool in main.m your're suggesting. However, ironically it is not effective at all, as iPhone apps terminating do no exit from UIApplicationMain, but via an exit() somewhere within UIApplicationMain. I thought this was a bug a while ago reported it to Apple. Their answer was: this is by design, do not rely on app exiting from UIApplicationMain, the place to do cleanup is applicationWillTerminate: and nowhere else.
I'm also not convinced creating and deallocating a global pool from an arbitrary point within your program flow really works. IMHO ugly things happen if you release a pool down in the stack while others are still on top. And how do you know how many pools are open at the time you want to call your +deallocAutoreleasePool?
(I autorelease objects for convenience, eg in getProperty()
, allocating a string to copy the property name from JS back to ObjC then autoreleasing it as I don't want to release it at each return of the function or use goto
.)
> I would create an autorelease pool around the JSCocoaController initialization and call to evalJSFile:
evalJSFile
will create ObjC classes that will be called back during NIB loading. Creating an autorelease pool just before calling, calling, then releasing the pool would remove the autorelease objects — that's what I want. This would work fine if I'm the only one autoreleasing, but the runtime might autorelease too, or the .js might be using functions like performSelector:withObject:afterDelay
that would maybe leak if they happen before the runtime creates a new pool.
> Try putting an NSLog([NSString stringWithString:@"hi"]);
after your call to NSApplicationMain()
in a JSCocoa app.
You mean right in main.m
? Doesn't crash nor even log. Even a basic NSLog()
fails to display anything — nothing shows up in the console or in console .app .
> I realize that's a real edge case, and that it may not really affect JSCocoa programs. But the bending of the autorelease pool conventions makes me cringe. At the very least I would leave a normal pool in place beneath your "remote-control" pool.
I don't think autorelease pools have any concept of 'beneath', just a stack getting pushed and popped by every pool alloc/dealloc. What I'm doing is popping that stack leaving it empty, then right after adding a new pool to it. That's why your NSLog
doesn't crash as that pool is still in place. Which, thinking about it, might be BAD :) It should be released too after NSApplicationMain
.
//
I'm well aware this is kludgy, but it works :) A cleaner solution would be to not use any JSCocoa objects in MainMenu .nib, and starting JSCocoa in the application delegate's awakeFromNib
. I really like having an app delegate written in Javascript, but I might use a 'proxy' ObjC one and replace it with a JS one in awakeFromNib
. I think I'll go down that route.
Well...I would create an autorelease pool around the JSCocoaController initialization and call to evalJSFile:
. (I'm not familiar with JSCocoa, true, so maybe this isn't quite what you want.)
If you mean you need the objects to hang around until after the nib is loaded, well, I'm not sure you should be using autorelease then anyway; it breaks the semantics of "I'm done with this, if the caller wants it they better retain it". Classes in particular are supposed to stick around for the lifetime of the program.
I was going to suggest a safer variant which deallocated and reallocated the autorelease pool at the same time, but then I realized that both versions have a serious problem: when -awakeFromNib
is called, AppKit has its own autorelease pool on the top of the autorelease stack. The pool you release is beneath that. If, by chance, the program pops its pool and does something, the "active" autorelease pool will have died already.
Try putting an NSLog([NSString stringWithString:@"hi"]);
after your call to NSApplicationMain()
in a JSCocoa app. If my suspicion is correct it'll crash or at the very least log an error...even if you put a third autorelease pool beneath the one from your method (e.g. [NSAutoreleasePool new]
as the first line of your main function).
I realize that's a real edge case, and that it may not really affect JSCocoa programs. But the bending of the autorelease pool conventions makes me cringe. At the very least I would leave a normal pool in place beneath your "remote-control" pool.
I care about this because JSCocoa loads .js classes used by NIBs, and they must be created before NSApplicationMain
loads the NIB. Using a top level autorelease pool will make some objects stick around until program end.
Popping the top pool kills objects when they're not needed anymore instead of killing them at program end. As JSCocoa logs instance count for debugging purposes, it allows me to check JSCocoa's GC logic.
The issue here is to have autoreleased objects used before NSApplicationMain
, and discarded before program end. If you have a better solution I'll take it !
Oh, not to mention that AppKit creates and releases an autorelease pool around every run-loop cycle. It's not like random objects are sticking around anyway.
shudders This is awful...so many Cocoa classes depend on an autorelease pool being around. Autorelease pools stack anyway; if you really care about this, just create a new one in -awakeFromNib
or -init
. Except...then you might end up with your app delegate effectively holding onto its own reference. (You have that with your scheme as well.)
Why would you need such a thing? You shouldn't really be relying on -dealloc
being executed anyway...that's what -applicationWillTerminate:
is for.
@millenomi great stuff with the homepage YAML syntax :) It would be sheer hell in XML.
@Robert No problem :)
http://www.iro.umontreal.ca/~lapalme/ForestInsteadOfTheTrees/HTML/ch08s03.html has a XML -> JSON transformer.
Also, @sjamesu on Twitter pointed me to HAML http://haml.hamptoncatlin.com/ — looks nice too.
Ideally I'd like to convert the result back to XML. Although I don't like XML, I really like XPath.
Heh - I was just going to suggest YAML - until I saw everybody else did already ;)
Now you've got me wondering if there are transformers between those markups. There's some help here: http://www.ibm.com/developerworks/forums/thread.jspa?messageID=21461
JSON is more or less a subset of YAML, so we're good at least one-way.
(Oh, and sorry for abusing your blog as part of my Google outboard brain - but I figured it was at least somewhat relevant to you, too)
What about YAML? www.yaml.org (the home page is valid YAML, if you want a sample.)
> Isn't in this case self already pointing to the right place after [super init]
No. An ObjC method is a C function taking two extra arguments : the instance and the selector. self
does nothing more than point to that instance argument.
[super init]
returning a new object (which does happen, see Mike Ash's article) means self
has been destroyed — you need to account for that. The one valid object you have is the one returned by the parent init
.
Correct me if I"m wrong: Always return from an -init whatever you have set self to. Even if you have to exchange the instance. Everything else is BAD style and WRONG.
Apples classes respect this (except for the obvious class clusters), and you should, too. And if that is the case it will work without the assignment.
But even if the superclass deallocates self and points it to another instance: Isn"t in this case self already pointing to the right place after [super init], thus making the assignment optional?
Hehe :) Didn't he concede after a guy wrote that program to test all ObjC classes ?
Obligatory link to Wil Shipley's blog :) http://www.wilshipley.com/blog/2005/07/self-stupid-init.html
Here's a command line wrapper I threw together: http://tlrobinson.net/blog/?p=55
(English below ! :) )
Oui, c'est possible. Pour l'instant, tout est ouvert et l'interpreteur passe par 2 endroits pour appeler des fonctions C ou Cocoa :
OSXObject_getPropertyCallback
recupere les fonctions C classes ObjC, constantes : filtre propertyName
pour interdire des fonctions C ou classes ObjC (interdire tout acces a NSView par ex)jsCocoaObject_getProperty
recupere les propriétés des instances : le nom d'un method, d'un propriété : filtre propertyName
et inspecte callee
pour interdire l'acces a des methodes ou propriétés d'une instance.// English !
Right now everything is open : anyone can call anything : any C function, class method, …
propertyName
in OSXObject_getPropertyCallback
alloc
and init
in NSView
) filter propertyName
with the help of callee
(the instance being called) in OSXObject_getPropertyCallback
Ce projet à l'air vraiment prometteur, je vais le suivre avec attention. :) Est-ce que c'est possible d'isoler l'interpreteur de script afin d'éviter que les scripts puissent atteindre toute l'application hôte ? (Pour faire un système de plugins JavaScript, par exemple).
Stuff like open
and write
work just fine, but how do you use stuff like ioctl
? The man page is bare, the header file also, googling it yields differents results for Linux, BSD, …
The main problem I have with file descriptors is finding documentation on the concept. I know that everything is a file, but using it is practice made me pull my hair. In NSLogConsole, I redirected stderr output to a pipe, this worked just fine when launched from XCode or the Terminal, but blocked when launching from Finder. Seems like because XCode and Terminal open a TTY before launching the app and redirecting stderr to a pipe works fine here, but blocks from Finder.
I tried opening dev/tty
, tried to google some more info about pipes, async sockets, (and some exotic options to set with … ioctl
), file descriptor concepts and came up with nothing working — I tried the UNIX way and failed, I tried the Cocoa way and succeeded pretty quickly.
> You like performance, I prefer convenience ;)
Very true.
> I've dabbled with open/read/write while writing NSLogConsole and quickly came back to ObjC
Keep in mind Objective-C is a superset of C.
> functions like open are unsearchable
Man pages contain example usage, possible pitfalls, existing bugs... Cmd-double click in Xcode to bring up the header file is also extremely useful. (I usually have more trouble with the framework references than with libc)
Not caring when the memory is released is exactly the point :)
The lifetime of malloc_autorelease
memory is the same as autoreleased objects like [NSURL URLWithString:…]
and serves the same purpose : use some data now and don't care when it's freed, thanks to dataWithBytesNoCopy
that will do it for us.
This has the odd side effect of the malloc'd memory being deallocated when the nearest autorelease pool as opposed to an explicit free. Since you're not returning the NSData* there is no way to retain the value for use later.
If you're method returned an NSData, you could still get at the element
NSData* tempData = malloc_autorelease(sizeof(element) * elementCount);
element* myTempData = (element*) [tempData bytes];
[tempData retain];
...
[tempData release];
You like performance, I prefer convenience ;)
I've dabbled with open/read/write
while writing NSLogConsole and quickly came back to ObjC — functions like open
are unsearchable, and I've had trouble finding documentation for stuff like ioctl
. Even if createFileAtPath
is slower, it's much easier to use.
Both createFileAtPath:contents:attributes:
and writeToFile:atomically:encoding:error:
ultimately call open
anyway, but you get a lot of additional overhead. Better to do it yourself: man 2 open
Windows likes to use a BOM for UTF-8, but I don't we have that particular problem on OS X.
The file shows up as zero length in Terminal. According to Wikipedia, the BOM is used for UTF8 and UTF32 http://en.wikipedia.org/wiki/Byte%5FOrder%5FMark .
Apparently there is no way to mark the file with a particular encoding … maybe with metadata ?
Not a Unicode expert, but I imagine the string @""
with utf-8 encoding would write with a byte order mark at the beginning.
Nothing ! I used writeToFile
because it was the first thing I found in the help.
What's wrong with [[NSFileManager defaultManager] createFileAtPath:logPath contents:[NSData data] attributes:NULL];?
Alas I've never used Smalltalk !
As for numbers and nil …
// Create an NSNumber
[@6.5 message];
// Create an NSNull
[@nil message];
// Bools too ?
[@YES message];
We could always lobby Apple for that :)
i think it looks more like Smalltalk than Javascript ;-) now if numbers and nil would also be objects, that'd be nice, but that's not gona happen in Obj-C :-)
Karsten
MIT license. Use freely !
Right now, launching from the Finder blocks on reading … works fine in XCode and Terminal. So don't use in production code :) Somehow stderr doesn't behave the same from Finder and from XCode. Any ideas ?
wow, great tool...thx!!
is there some sort of restriction to the source? or is it public domain?
Karsten
Thanks Rainer !
I did Google 'malloc autorelease' before writing that post, without finding anything relevant. I need to level up my Google-fu …
For more variations: http://borkware.com/quickies/single?id=385 and http://borkware.com/quickies/single?id=352 ...
@Russell I've gone back reading NSData's doc and indeed both are equivalent. I didn't know dataWithBytesNoCopy:length:
freed its pointer, its variant dataWithBytesNoCopy:length:freeWhenDone:
apparently exists to create an NSData
that will not free the pointer.
So dataWithBytesNoCopy:length:
will work just as well !
Great tip, but I'm puzzled by one thing: isn't dataWithBytesNoCopy:p length:size freeWhenDone:YES
equivalent to simply dataWithBytesNoCopy:p length:size
? Or is there some subtle point I'm missing?
Whoops! You're right. Of course I go re-read your post after I submitted my comment. As long as there's an autorelease pool in scope, it will work. Sorry!
-[NSData dataWithBytesNoCopy:length:freeWhenDone] does not return void. It returns an NSData object that frees its buffer when it is dealloc'd. Since you throw away that NSData object, your implementation will never free the allocated buffer.
@ankur I'm doing that for convenience. I could shuffle around the code and free the data right in the function, but that's not high reward work as I'm not looking for speed in that particular case.
After considering goto
, I think the best solution is to define a function named malloc_autorelease
that will do just what its name implies - hiding the autoreleasing of the pointer and allowing to write code without thinking about memory freeing.
@Bill I'm pretty sure doing free(ptr)
if ptr = NULL
is safe.
But you're right that you ideally should be checking if malloc
returned NULL
. Although it would likely mean you'd run out of memory, and the whole program would 'blow up' anyway!
Autorelease is expensive. Eliminate the BOOLs and do if(... || ...)
rather than having two separate if statements. "Without PointerFreer" will be only one line longer than "With PointerFreer" and a heck of a lot faster.
@Ankur sometimes it's just not an option to delay malloc. That's doable, but that usually implies one call to count the elements and another to actually fill data — not delaying malloc makes that just one pass.
@Bill good point ! But as I didn't check for NULL after malloc(), I think it will blow up before reaching the free ;)
@Dmitry I'd missed the return success
. Ok, I'll stop spurning goto
now.
But if you want to return YES or NO depending on your result, you still have to set a BOOL so that the goto can know what to return — or am I missing something?
See return success; in my example of goto.
Nice to see the Linux guys embrace goto !
I've just made a search and found 6695 goto's in the sources of XNU kernel. So Mac OS X guys also embrace goto ;) If you want an "approval" of a Cocoa programmer, here it is.
In -setPointer:, you don't sanity check the argument for a NULL value. If you allow ptr
to be assigned a NULL value, things will ultimately go boom when free(ptr)
eventually gets invoked by -dealloc:
Why not just defer the malloc until after checking the conditions?
BOOL myFunction(...) {
if(condition << anotherCondition) {
myType* data = malloc(sizeof(myType)*elementCount);
doSomeStuffWithData(data);
free(data);
return YES;
} else {
return NO;
}
}
> Do you really need two classes to manage pointers ?
No, but I do need a better way to search the docs :)
NSData already does this. See:
Do you really need two classes to manage pointers?
Nice to see the Linux guys embrace goto
! But if you want to return YES or NO depending on your result, you still have to set a BOOL so that the goto can know what to return — or am I missing something ?
Yes I did mess up by calling it initWithPointer
— I'll fix that. Thank you !
BTW, by Cocoa conventions, you it's better to call your class method pointerFreererWithPointer or something like this, because initWith... are assumed to be instance methods, which return non-autoreleased objects. (Not that it's a restriction of some kind, just a convention).
Using "goto" is really nice way to do cleanup, don't be afraid of it :) Arguments here.
BOOL myFunction(...)
{
myType* data = malloc(sizeof(myType)*elementCount);
// Check for something
BOOL success = ...
if (!success)
goto cleaup;
// Check for something else
success = ...
if (!success)
goto cleanup;
// Actual work !
doSomeStuffWithData(data);
// And free temp data
cleanup:
free(data);
return success;
}
Also, don't forget that with GC -dealloc is never called, so it's safer to have -finalize as well it you think you'll ever use your code in GC-required app ;)
Ah, yes. Thank you !
So … XCode warns about no rule to process file
when the .js is in the wrong build phase. It uses CpResource
to copy the .js if it's in the right build phase (Copy Bundle Resources).
It's in libSystem, so you don't (readily) have the code for it. You can use the Breakpoints window to create a symbol breakpoint for it by hand, though.
The clickable thingy is genius. In fact, TextMate does that with many kinds of error messages, for example PHP errors, and it's supremely useful there.
For those who (like me) hadn't ever heard the word "doxa": it's the governing opinion, which is sublated through logos to episteme. Also a brand of watches. Wikipedia rules.
Indeed, but you have to repeat the condition :( which may be more complicated than if (node)
.
You could also use a do while
loop:
node = firstNode;
do {
if (! someConditionOnNode )
continue;
compute !
} while ((node=node->next));
Note that this doesn't test for node
being non-NULL
initially. To do this you could probably just stick an if
statement before like:
node = firstNode
if (node) do {
...
I've made the feed valid, I hope this fixes the duplicating.
If that doesn't do it, I'm out of options :)
If classes are objects, where are they defined ? I didn't find
@interface Class
in the headers. That's what I don't get about classes : they do behave like objects but Class is defined as a struct !?
Classes are objects. They are of class Class. As mentioned before, you rarely need to actually know to what class an object belongs; just ask it -respondsToSelector:
or -conformsToProtocol:
. But if you really need to know if you're dealing with an object of a specific class Foo
, just ask [obj isMemberOfClass:[Foo class]]
. Putting two and two together, if you want to know if a specific object obj
is actually a class, ask [obj isMemberOfClass:[Class class]]
.
@Robert I'm writing a bridge from JavascriptCore to Cocoa and I need to know what kind of object the interpreter is giving me back. Agreed, that's extremely useless in everyday programming but that makes a nice blog post !
@Karsten You get my vote for pragmatic programming :)
@Dmitry Thanks for the hack ! So there is no official method. Frustrating since NSStringFromClass seems to be using the unofficial one …
First:
BOOL isClass = ![object1 isMemberOfClass:[object1 class]];
Seems like class is not a member of itself ;)... However docs say:
"Class objects may be compiler-created objects but they still support
the concept of membership. Thus, you can use this method to verify
that the receiver is a specific Class object."
Second, total hack:
BOOL isClass = (NSStringFromClass(object1) != nil);
why not implement a method: +isClass and -isClass or +isInstance and -isInstance in Object?
nothing to compare then, just return a YES and a NO in the right methods ;-)
Karsten
There is very rarely a need to know your class.
There are two places I know of where you (sort of) need to know a class.
1) You're working on backwards compatibility, some methods are only supported on newer versions of the OS. Use respondsToSelector: to figure out if your object is OK
2) You want to verify your object can behave a certain way. All you need to determine is if it conforms to a specific protocol - use conformsToProtocol:
That way, any implementation that satisfies those less stringent requirements will still work - you're not tied to your original choice of class.
I just checked with feedvalidator.org and my feed doesn't validate, I'll see how to fix that.
Ouch ! How can that even happen ? I don't use NNW syncing, maybe the problem comes from here ? Have you tried unsubscribing then subscribing again ?
I didn't touch these CA posts after the template bug fix, Google reader does not mark them as new, NNW without syncing doesn't either, so I'm at loss why they keep getting popping up in your reader.
Just to show you how bad it is getting:
http://public.toxicsoftware.com/parmanoir.png
Maybe it is because I'm using newsgator syncing?
Several one in a day ?! Wow !
I don't know what to do, I sometimes launch NNW (3.1.5) to check the feed and I've never seen a read item not read.
:(
Yes, it's really a nice solution. It's too bad that Apple is using it to nag you into paying for more software instead of using it as help.
One nice example of this mechanism as help would be in Pages, for 'Instant Alpha' : its activation is not obvious — it only works on an image selection — and opening a window explaining that would be nice.
I think this really is the solution to this problem. It is obvious at first look that the menu item is disabled and thus the user knows that it won't work right now. The "PRO" label also tells the user that they need to purchase the pro version of the application to enable the functionality, and if they need more info about it, they can just click the menu item.
Once more, Apple solved the problem before we even knew there was one.
I do get an error in this case. However, the original post is wrong — see my first comment, I copied the code and over cleaned it up to make it shorter.
Patrick: Yes, that will crash. But the compiler should raise an error if you try to call the function with a different number of parameters, as your original code did. In fact, I tried to compile the following with gcc and got an error:
double (*fn)(void);
fn();
fn(2);
I tried adding the void, to no avail. The problem doesn't seem to be the first function definition, but that you can call any function pointer that hasn't been initialized :
double (*fn)(void);
fn();
will crash without any compile-time warning.
Should you have declared fn as 'double (*fn)(void) = sym;' (note the void in between the parenthesis), I expect the compiler would have detected an error in any kind of build; wouldn't it?
Argh … I messed up while copying and cleaning up the code for posting. I didn't assign to fn2 and then I called that undefined function pointer. It looked like this :
// No assignment
SomeStruct (*fn2)(float, float, float);
// Misassign to first pointer
fn = sym2;
// Call of undefined pointer
fn2(1, 2, 3);
GCC does catch the bug in the post, but not that one.
Moral2: You might want to crank up warnings to the highest level. In that case, you would have gotten a warning that you assigned to fn2 but never used the value.
(Not sure if gcc does that - spending too much time in VS.NET land these days)
Works best in Firefox 3. I just tested Webkit's nightly, it still locks up for up to 30 seconds in some cases. Firefox will just take 1-2 seconds to redisplay.
Just tried NSUndoManager's valueForKey:@"_undoStack" and it works like a charm. Great tip, merci bien !
An alternate (quick and easy) way of accessing private ivars is to use KVC, in particular -valueForKey: and -setValue:forKey: . Although some classes may trap this, most don't and it's a very useful technique that I use often (actually I used it too while in gdb console to inspect NSUndoManager stacks).
=begin … =end confused me too, and googling '=begin' to guess why they need to be positioned exactly at the start of the line or they won't work whas a pain.
That said, there are things I really love in Ruby, namely the return if (condition), the ability to omit parens in if/while/…. Too bad we can't cherry pick features from languages to make our own :)
Ruby does have multiline comments. Multilines comments begin with =being and end with =end, although this confused me a lot when I first learned Ruby.
Also, coming from JavaScript to Ruby, I prefer the braces syntax over the do...end syntax when using blocks precisely because it's more syntactically similar to JavaScript.
Any idea why it's 'faked' and just one way ? It seems like more work than just making a 'value' property KVC compliant.
Yes there is, you use the accessors defined in NSControl (objectValue
, doubleValue
, floatValue
, intValue
, stringValue
).
Binding to something requires a KVO-compliant key. Binding from something can evidently be faked (or at least renamed).
Browsing the logs I've seen someone from netblock-68-/-/-/.dslextreme.com trying to leave a comment here. I was doing some work on the admin side and your comment didn't make it through. Sorry ! Please repost if you come back.
Yes, we need to be careful about overlapping : I had an NSTableView slightly overlapping an NSBox, it repainted over the NSBox on scroll.
Note that in this case it worked well only when Core Animation was enabled.
//
I just got back to that overlapping NSBox, enabling Core Animation removes any repainting problems too. Nice :)
That is a very cool idea, but I'm torn because AppKit has never assured that overlapping views work. The Adding and Removing Views from a Hierarchy part of the View Programming Guide warns against it.
In practice, though, I've done this before too.
Ah yes, using NSPopUpButtonCell's attachPopUpWithFrame:inView: allows you to specify a rect. I hadn't seen that. Thank you !
I would think that the better way would be to include an NSPopupButtonCell that you don't draw but still pass mouse events to.
I hope everything's OK from here on.
As for CATiledLayer, I don't even understand its use. Don't expect sample code soon :)
That's great. I was wondering what was causing it. Keep up the good work with your CoreAnimation articles though.
I hope you tackle the secret gotches of CATiledLayer next. ;-)
That's because they are updated :) I use a template at the bottom of the Core Animation posts, when I add a new post I'll update the template with it and the old posts will get the new version of the template as well. I didn't realize this would mark the old posts as new. I'll look into it.
Hey there, your blog is awesome. I love the CoreAnimation postings especially. However, for some reason NNW keeps thinking your site is constantly updating the old blog posts and they keep appearing in my feed. I'm wondering if the problem is your end and if you'd take to look at fixing it?
Cheers.
Just found this http://s-take.blogspot.com/2008/04/image-kit.html
… anybody read Japanese ?
Pour être précis, cette "règle de la main droite" signifie géométriquement qu'on choisit une base orthonormée directe de l'espace de dimension 3, alors qu'utiliser la main gauche conduirait au choix d'une base indirecte de l'espace ... ce qu'on fait moins souvent dans la pratique, pour des raisons de convention: sinon, il faudrait par exemple changer l'expression matricielle des rotations en dimension 3, etc. etc. Enfin, tant que c'est de la 2d augmentée, il faut juste savoir que l'axe des Z pointe vers le codeur et non pas l'écran !
Ah thanks, I didn't know the official name, just "* handed".
Anyway if you come from DirectX and code in Core Animation, hands are reversed. In a 3D engine, setting a badly signed Z value on layers would make them invisible. CA did draw them, inversely sorted.
Hi Karsten,
Ah yes, jrswizzle copies the parent implementation at the derived class level with class_addMethod. So it is simpler ! Thanks for the link.
wouldn't it be simpler to just use MethodSwizzling for that? Jonathan Rentzsch did a nice project to have a clean implementation of it. Michael Tsai bloged about it here: http://mjtsai.com/blog/2007/12/29/jrswizzle/
Karsten
No. Google Analytics is a piece of Javascript, I doubt it'd work in a RSS feed. And I only put the code in the website.
Does it count RSS readers too? 'cause when you have (like me) NetNewsWire configured to refresh feeds every hour, it increases the daily number of hits by a larger factor than just web visitors.
Woops ! Maybe I should have Bloom disabled by default. But it's so much prettier ... :)
Nice code!
Runs like a dog on Macbook (1st gen) until you turn bloom filter off. Then runs really smoothly.
Subscribed!
There's actually a "sphereContainer" sublayer that holds all of the floating orbs. I'm not sure what the exact effect was that you were going for, I changed this line:
mainLayer.sublayerTransform = transform;
To this:
sphereContainer.sublayerTransform = transform;
And it looks a lot better. I think Core Animation is actually doing the right thing. The NSView's backing layer had the sublayerTransform applied, so the sphereContainer layer was floating out in space.
I don't think this is correct. X right, Y up and Z out of screen is right-handed. But CoreAnimation is not Y up, it is Y down. So it is actually left-handed, but with Z out of screen.